Go struct

As of go1.22.5, the Go programming language does not have the concept of "classes" nor does it support object-oriented concepts such as class inheritance. Instead, Go achieves extensibility and flexibility through embedding structs and interfaces.

Struct Declaration

type structName  struct {
   fieldName1 fieldType1
   fieldName2 fieldType2
   …
}

Struct Embedding

Go mimics inheritance through struct embedding:

type Contact struct {
   Phone   string
   Address string
}
type User struct {
   Name string
   Sex  string
   Contact
}

Struct Instantiation - Regular Way

var u1 User
u1.Name = "Flasle"
u1.Sex = "Male"
u1.Phone = "1*****"
u1.Address = "New York"

Struct Instantiation - Using new

var u2 = new(User)
u2.Name = "Flasle"
u2.Sex = "Male"
u2.Phone = "1*****"
u2.Address = "New York"

Struct Instantiation - Taking the Address

u3 := &User{}
u3.Name = "Flasle"
u3.Sex = "Male"
u3.Phone = "1*****"
u3.Address = "New York"

Initialization with Key-Value Pairs

Fields without specified initial values will take the default value of their type.

u4 := User{
    Name: "Flasle",
    Sex:  "Male",
    Contact: Contact{
        Phone:   "1*****",
        Address: "New York",
    },
}

or

u5 := &User{
    Name: "Flasle",
    Sex:  "Male",
    Contact: Contact{
        Phone:   "1*****",
        Address: "New York",
    },
}

Initialization with a List of Values

All fields of a struct (including embedded structs) must be initialized, and the order of initialization must match the order of declaration.

u6 := &User{
   "Flasle",
   "Male",
   Contact{
       "1*****",
       "New York",
   },
}

Methods and Receivers

In Go, a method is a function that operates on a specific type of variable, and the concept of a receiver is analogous to this or self in other languages.

func (receiverVariableName ReceiverType) MethodName(parameterList) (returnTypeList) {
    Method body
}

The receiver type, similar to parameters, can be a pointer type or a non-pointer type.

Value Receiver

When a method operates on a value receiver, Go makes a copy of the receiver's value at runtime. Within the method, you can access the receiver's member values, but modifications are made to the copy, not the receiver variable itself.

type User struct {
   Name string
   Age  int
}
func (this User) SetAge1(age int) {
   this.Age = age
}
u1 := &User{
   "Flasle",
   18,
}

fmt.Println("before:", u1.Age)
u1.SetAge1(20)
fmt.Println("after:", u1.Age)

#before: 18
#after: 18

Pointer Receiver

A pointer receiver consists of a pointer to a struct. Due to the nature of pointers, any modifications made to the receiver's member variables during the method call persist after the method ends.

func (this *User) SetAge2(age int) {
   this.Age = age
}
u2 := &User{
   "Flasle",
   18,
}

fmt.Println("before:", u2.Age)
u2.SetAge2(20)
fmt.Println("after:", u2.Age)

#before: 18
#after: 20

When to use Pointer Receivers?

  1. When you need to modify the receiver's values.
  2. When the receiver is a large object with a high cost of copying.
  3. To ensure consistency: if one method uses a pointer receiver, other methods of the same struct should also use pointer receivers.

Struct Tags

Tags are metadata for structs and can be read at runtime through the reflection mechanism. Tags are defined after a struct field, enclosed by a pair of backticks (``):

`key1:"value1" key2:"value2"`

A struct tag consists of one or more key-value pairs. The key and value are separated by a colon, and the value is enclosed in double quotes. The key-value pairs are separated by a single space. Notes: When writing tags for structs, it is imperative to strictly follow the key-value pair rules. The error tolerance of the parsing code for struct tags is low. If the format is incorrect, neither compilation nor runtime will indicate any errors, and the value cannot be retrieved correctly through reflection. For example, do not add spaces between the key and value.

type User struct {
   Name string `json:"name" xml:"Name"`
   Age  int    `json:"age" xml:"Age"`
}
u3 := &User{
   "Flasle",
   18,
}
data, err := json.Marshal(u3)
if err != nil {
   fmt.Println("json marshal failed!")
   return
}
fmt.Printf("json str:%s\n", data)

#json str:{"name":"Flasle","age":18}
  1. xxx.Marshal serializes xxx object into a string based on the struct tags, i.e., Name is mapped to name β†’
  2. xxx.Unmarshal deserializes a string into xxx object based on the struct tags, i.e., name is reverse-mapped to Name ←

 

Take a break

πŸ‘‰πŸ‘‰πŸ‘‰ 【BTTH Year EP92】Xiao Yan vs Hong Chen