Original author, public number [programmer reading], welcome to pay attention to the public number, reprint the article please indicate the source oh.

The Go language provides support for structs, structs, like arrays, are compound types, not reference types.

Structs in Go, like structs in C or classes in other object-oriented programming languages, can define fields (attributes) and methods, but there are also significant differences that require further study to distinguish them.

Note the difference between compound types and reference types, and this should be the difference between value passing and reference passing.

define

You can use the struct keyword to define a structure, whose members are called fields or properties of the structure.

type Member struct {
    id          int
    name, email string
    gender, age int
}
Copy the code

In the above code, we define a structure containing five fields. We can see that the same type name is defined in the same line as email, gender, and age. It is a good programming practice to define only one field per line.

type Member struct {
    id     int
    name   string
    email  string
    gender int
    age    int
}
Copy the code

Of course, struct{} can also contain no fields, called an empty struct. Struct {} represents an empty struct. Note that it is not meaningful to define an empty struct directly, but in concurrent programming, communication between channels can use a struct{} as a semaphore.

ch := make(chan struct{})
ch <- struct{}{}
Copy the code

use

In the example above, we defined the Member structure type, which is then used to create variables.

Define variables directly. This is used without assigning an initial value to a field, so all fields are automatically assigned a zero value of their type, such as name with an empty string “” and age with a value of 0.

Var m1 Member// All fields are nullCopy the code

Use literal creating variables, this way of using, can be in curly braces for an initial value, a member of the structure are an initial value, there are two ways, one is according to the order of the fields in the structure assignment, m2 in the following code is to use this way, this approach requires that all fields must be assignment, so if the field is too much, each field to assign a value, it will be very tedious, The other way is to assign a specified field using the field name, such as the creation of variable M3 in the following code, and use the zero value of that field type as the initialization value for other fields that are not specified.

var m2 = Member{1,"Xiao Ming"."[email protected]"M2 := Member{1, 1,1}"Xiao Ming"."[email protected]",1,1} var m3 = Member{id: 1, 2}"name":"Little red"} m3 := Member{id:2,"name":"Little red"}
Copy the code

Access to the field

With the variable name, use a comma (.) , you can access fields in struct types, assign values to fields, and address (&) fields.

FMT.Println(m2.name)// Output: xiaoming m3.name ="Flower"FMT.Println(m3.name)// Output: floret age := &m3.age *age = 20 fmt.println (m3.age)//20Copy the code

Pointer structure

Structures like arrays, are passed values, such as when an array or a structure as the arguments passed to the function parameter, can copy a copy, so in order to improve the performance, general won’t put an array is passed to the function directly, but instead USES slicing (reference type), and pass function, the structure can use pointer structure.

A pointer to a struct is a pointer to a struct. When declaring a struct variable, add an * before the struct type to declare a pointer to a struct.

Note that the pointer type is a reference type. When declaring a structure pointer, if it is not initialized, the initial value is nil, and the field can be accessed or assigned only after initialization.

var m1 *Member
m1.name = "Xiao Ming"M1 = &member {} m1.name ="Xiao Ming"// After initialization, the structure pointer points to a structure address to access the field and assign a value to it.Copy the code

In addition, using the Go built-in new() function, you can allocate memory to initialize the structure rest and return a pointer to the allocated memory, since the fields are already initialized and can be accessed directly.

var m2 = new(Member)
m2.name = "Little red"
Copy the code

We know that if the structure to the function, just copy a copy of the structure, if the modified structure field values within the function, the outside structure will not be affected, and if the structure pointer to function, is used in the function pointer to structure changes, will affect the pointer to the structure of the body.

func main() {
    m1 := Member{}
    m2 := new(Member)
    Change(m1,m2)
    fmt.Println(m1,m2)
}

func Change(m1 Member,m2 *Member){
    m1.Name = "Xiao Ming"
    m2.Name = "Little red"
}
Copy the code

visibility

In the example above, we define struct field names to start with lowercase letters, which means that these fields are not visible outside the package and therefore cannot be accessed in other packages, only within packages.

In the following example, we declare Member in the Member package, and then create a variable in the main package, but because the structure’s fields are not visible outside the package, we cannot assign the initial value to the field, either by field or by index, which causes panic.

package member
type Member struct {
    id     int
    name   string
    email  string
    gender int
    age    int
}

package main

fun main(){
    var m = member.Member{1,"Xiao Ming"."[email protected]",1,18}// will cause panic error}Copy the code

Therefore, if you want to access the fields of a structure in one package, you must use variables that begin with a capital letter, exportable variables such as:

type Member struct {
    Id     int
    Name   string
    Email  string
    Gender int
    Age    int
}
Copy the code

Tags

When defining a structure field, in addition to the field name and data type, you can use backquotes to declare meta information for the structure field. This meta information is called Tag and is used to associate the structure with the field at compile time. For example, we changed the structure in the above example to:

type Member struct {
    Id     int    `json:"id,-"`
    Name   string `json:"name"`
    Email  string `json:"email"`
    Gender int    `json:"gender,"`
    Age    int    `json:"age"`}Copy the code

The above example demonstrates the Tag information used to encode or decode structures using the Encoding/JSON package.

A Tag consists of a series of space-delimited key:”value” pairs enclosed in backquotes, as in:

Id int `json:"id" gorm:"AUTO_INCREMENT"`
Copy the code

features

The relevant characteristics of the structure are summarized as follows:

Value passed

Structs, like arrays, are compound types, which are passed as arguments to functions or assigned to other variables.

No inheritance

The Go language supports object-oriented programming, but there is no concept of inheritance, where more complex structures can be built by combining other structures.

A structure cannot contain itself

A structure that does not contain itself, such as a field in Member that cannot be of type Member, but may be *Member.

methods

In Go, a function bound to a specific type is called a method of that type. This is defined by inserting a specific type variable between func and the function name. This type variable is called a method sink, as in:

Note that methods can be bound not only to structures, but to any type, but to a structure.

func setName(m Member, Name string){// common function m.name = Name} func (m Member)setName(Name string){// bind method to Member structure m.name = Name}Copy the code

From the above example, we can see that the structure’s fields can be accessed through the method receiver, which is similar to the this keyword in other programming languages, but in Go, it is just a variable name and we can name the method receiver any way we want.

The method for calling a structure is the same as for calling a field:

m := Member{}
m.setName("Xiao Ming") FMT.Println(m.name)// The output is emptyCopy the code

The setName() method is called to set the value of field Name. Why is the output still empty?

This is because the structure is passed by value, and when we call setName, the method receiver receives only a copy of the structure variable. Fixing the value through the copy does not affect the caller. Therefore, we can define the method receiver as a pointer variable to achieve the purpose of modifying the structure.

func (m *Member)setM := Member{} m.setName(*Member {} m.setname)"Xiao Ming") FMT. Println (ame) / / xiao MingCopy the code

Methods, like fields, are only allowed to be visible within the package if they start with a lowercase letter and are not accessible in other packages, so if you want to access setName in other packages, you should change the method name to setName.

combination

As we know, there is no concept of inheritance in constructs. In fact, there is no concept of inheritance in THE Go language. The programming philosophy of the Go language recommends the use of composition to achieve code reuse.

What is a combination

Composition can be understood as defining a structure whose fields can be other structures, so that different structures share the same fields.

Note, before you remember what we said earlier, that a structure cannot contain itself, but may contain Pointers to a structure that points to itself.

For example, we define a structure named Animal for an Animal. If we want to define a structure for a cat, say:

typeAnimal struct {Name string // Name string // Colorfloat32 // Height Weightfloat32 // weight int // Age} // run func (a Animal)Run() {
    fmt.Println(a.Name + "is running"} // Eat func (a Animal)Eat() {
    fmt.Println(a.Name + "is eating")}type Cat struct {
    a Animal
}

func main() {
    var c = Cat{
	    a: Animal{
            Name:   "Cat",
            Color:  "Orange",
            Weight: 10,
            Height: 30,
            Age:    5,
        },
    }
    fmt.Println(c.a.Name)
    c.a.Run()
}

Copy the code

As you can see, when we define the Cat structure, we can use the Animal structure as the Cat field.

Anonymous fields

In the example above, we can see that the Animal structure is used as a field of Cat and its variable name is a, so we can access Animal methods with the syntax c.a.run ().

The Go language supports fields that have a type as a structure without taking a variable name. These fields are called anonymous fields, such as:

typeLion struct {Animal} funcmain(){
    var lion = Lion{
        Animal{
            Name:  "Little Lion",
            Color: "Gray",
        },
    }
    lion.Run()
    fmt.Println(lion.Name)
}
Copy the code

As you can see from the above example, it is very convenient to combine other types from anonymous fields and then access methods and fields of anonymous field types without using the leaf attribute.

summary

Structs are probably the most commonly used data type in Go programming. By defining structs for different fields and methods, and abstractly combining different structs, this is probably object-oriented programming in Go.


Your attention is the biggest encouragement on my writing road!