Object oriented programming in Go language

1, Basis of structural variable method

Structural variables not only have their own attributes, but also have their own methods. For example, a person not only has a name and age, but also has some behaviors. These behaviors can be understood as methods in structural variables. The methods in Golang are bound to specific data types, so it's not just the time structure that has its own methods.

(1) Quick start

1. Method declaration

func(receiver type) methodName(parameter list) (Return value list){

      Method body
      return Return value
    
}
  • Parameter list: indicates method input
  • receiver type: indicates that the method is bound to the type, or the method acts on the type
  • receiver type: type can be a structure or other user-defined types
  • receiver: is an instance of type
  • Return value list: indicates the returned value, which can be multiple
  • Method body: represents a block of code to implement a function
  • The return statement is not required

For example:

package main

import "fmt"

type User struct {
    Name string
    Age  int
}

func (user User) getUser() {

    fmt.Println(user.Name, user.Age)

}

func main() {

    var user User
    user.Name = "bily"
    user.getUser()

}
  • Func (User) getUser() {} represents the method of the User structure. The method name is getUser
  • (a) reflect getUser method and User type binding
  • The getUser method can only be called through the User instance
  • The user instance in the main function is not the same as the user instance passed in by the getUser method. The method is copied, and the structure is value transfer

2. Instance

package main

import "fmt"

type CalSum struct {
    n1 int
    n2 int
}

// Structure calls method, which can have input parameter and return value
func (cal CalSum) getSum() int {
    res := cal.n1 + cal.n2
    return res
}

func main() {

    // Generate a structure variable
    cal := CalSum{
        1,
        2,
    }
    // Call method
    res := cal.getSum()
    fmt.Println(res)
}

(2) In depth understanding of structural variable methods

1. Method calling mechanism

 

Methods are similar to functions, but the biggest difference is that the method will pass the caller to the method as a parameter. For example, Cal will be passed to the getSum method as a parameter in the above figure. It should be noted that if it is a value type, the value will be copied, and if it is a pointer type, the reference will be passed, which is related to the formal parameter type.

The default is value type transfer, which means that the structure variables in the method are copied from the main function, so the efficiency is low. In order to improve the efficiency, reference transfer can be carried out.

package main

import "fmt"

type CalSum struct {
    n1 int
    n2 int
}

// Structure calls method, which can have input parameter and return value
func (cal *CalSum) getSum() int {
    res := cal.n1 + cal.n2
    return res
}

func main() {

    // Generate a structure variable
    cal := CalSum{
        1,
        2,
    }
    /*
        Call the method. Because the formal parameter of the method is a pointer type, it should be called by the address of the structure variable
    */

    res := (&cal).getSum() // .The operation priority of is high, so(&cal)Parentheses are required
    fmt.Println(res)       // 3

    /*
        But the compiler is optimized at the bottom, so (& CAL) Getsum () can be written as cal getSum()
    */

    res1 := cal.getSum()
    fmt.Println(res1)

    /*
        At this time, the structure variable in main is the same as the structure variable passed in the method, and the existing form in memory is also different from the value transfer
    */

}

2. The method is not unique to the structure

Methods are not unique to struct types. For example, int and float series types can have methods:

package main

import "fmt"

type integer int

// integer Type method
func (i *integer) change() {
    *i = *i + 5
}

func main() {
    var i integer = 5
    i.change()
    fmt.Println(i) // 10
}

3. Differences between methods and functions

  • The function is called by function name (argument list) and the method is called by variable Method name (argument list)
  • For ordinary functions, the receiver is of value type, and data of pointer type cannot be passed, and vice versa
  • For methods, when the receiver is a value type, you can directly call the method with a pointer type variable, and vice versa
  • The real decision between the time value copy and the time address copy depends on the type with which this method is bound. If the time value type is (user User), it is the value copy, and if it is (user *User), it is the address copy

2, Factory mode

(1) Lead to problems

If there is a model package with a structure variable:

package model

// Define a structure
type User struct {
    Name string
    Age  int
}

If you create an instance of the User structure in other packages, such as the main package, there is no problem at this time, because the first letter of the User structure is uppercase, but if the User is lowercase, it is a private variable, which can be accessed in this package. What if you solve the problem of accessing private variables across packages? This requires the use of factory mode, which is simply to determine the way a public method provides an external interface.

(2) Solution

1. Normal scheme

  • User.go
package model

// Define a structure
type User struct {
    Name string
    Age  int
}
  • main.go
package main

import (
    "fmt"
    "go_tutorial/day12/factorMode/model"
)

func main() {

    user := model.User{Name: "lily", Age: 20}
    fmt.Println(user)

}
  • directory structure
├─factorMode
  ├─main
  │      main.go
  │
  └─model
          user.go

User It is OK that the structure variables in go are capitalized, but if they are lowercase, there will be a problem that private variables cannot cross package. In this case, the factory mode is used.

2. Factory mode solves the cross package problem of private variables

  • user.go
package model

// Define a private node
type user struct {
    Name string
    Age  int
}

// Factory method that the package can call
func NewUser(name string, age int) *user {

    return &user{
        Name: name,
        Age:  age,
    }

}
  • main.go
package main

import (
    "fmt"
    "go_tutorial/day12/factoryMode01/model"
)

func main() {

    user := model.NewUser("lily", 20)
    fmt.Println(*user)               // {lily 20}
    fmt.Println(user.Name, user.Age) // lily 20

}
  • directory structure
├─factorMode
  ├─main
  │      main.go
  │
  └─model
          user.go

3. Factory mode solves the problem of cross package of private fields

The above is the cross package problem of private structure variables, but if it is a private variable with lowercase initial letters in the structure, how to solve it?

  • user.go
...
// Private field name Factory method
func GetName(u *user) string {
    return u.name
}
...
  • main.go
...
func main() {

    user := model.NewUser("lily", 20)
    fmt.Println(model.GetName(user)) //lily

}

3, Example drill

Create a Box structure in which:

  • Declare that the three fields represent the length, width and height of the cube respectively, and obtain them from the terminal
  • Declare a method to get the cube volume
  • Create a Box structure variable to print the volume of a given size cube
package main

import "fmt"

type Cell struct {
    length float64
    width  float64
    height float64
}

func (cell *Cell) GetVolume() float64 {

    return cell.length * cell.width * cell.height

}

func main() {
    // Create a cube structure variable
    var cell Cell
    // Assign a value to each field
    fmt.Print("Please enter the length of the cube:")
    fmt.Scanln(&cell.length)
    fmt.Print("Please enter the width of the cube:")
    fmt.Scanln(&cell.width)
    fmt.Print("Please enter the height of the cube:")
    fmt.Scanln(&cell.height)

    // Method of calling structure variable
    res := cell.GetVolume()
    fmt.Println(res)

}

 

 

Keywords: Go

Added by egiblock on Sat, 22 Jan 2022 05:31:47 +0200