An introduction to the differences between copy of struct methods in Go and pointer passing

  • 2020-06-12 09:18:42
  • OfStack

The differences between GO language struct methods and struct pointer methods

First of all, I ordered 3 interfaces, 1 structure and 3 methods:


type DeptModeA interface {
Name() string
SetName(name string)
}
type DeptModeB interface {
Relocate(building string, floor uint8)
}
type Dept struct {
name string
building string
floor uint8
Key string
}
func (self Dept) Name() string {
return self.name
}
func (self Dept) SetName(name string) {
self.name = name
}
func (self *Dept) Relocate(building string, floor uint8) {
self.building = building
self.floor = floor
}

Then I wrote a few tests:


dept1 :=
Dept{
name: "MySohu",
building: "Internet",
floor: 7}
switch v := interface{}(dept1).(type) {
case DeptModeFull:
fmt.Printf("The dept1 is a DeptModeFull.\n")
case DeptModeB:
fmt.Printf("The dept1 is a DeptModeB.\n")
case DeptModeA:
fmt.Printf("The dept1 is a DeptModeA.\n")
default:
fmt.Printf("The type of dept1 is %v\n", v)
}
deptPtr1 := &dept1
if _, ok := interface{}(deptPtr1).(DeptModeFull); ok {
fmt.Printf("The deptPtr1 is a DeptModeFull.\n")
}
if _, ok := interface{}(deptPtr1).(DeptModeA); ok {
fmt.Printf("The deptPtr1 is a DeptModeA.\n")
}
if _, ok := interface{}(deptPtr1).(DeptModeB); ok {
fmt.Printf("The deptPtr1 is a DeptModeB.\n")
}

Printed content:


The dept1 is a DeptModeA.

The deptPtr1 is a DeptModeFull.

The deptPtr1 is a DeptModeA.

The deptPtr1 is a DeptModeB.

Assuming that T is struct, the following principles are followed in Go:

T's method set has only T Receiver (the recipient of a method) methods. *T method set contains all methods (T + *T).

So your example above dept1 should have methods: Name and SetName

while & dept1 has methods: Name, SetName, and Relocate

This is the type of Go that you need to pay attention to when you design your methods

The difference between copy of struct method and pointer in Go language

Let's take an example:


package main
import (
 "fmt"
)
type B struct {
 Name string
}
func(b B) Test1() {
 fmt.Printf("Test1 addr:%p\n", &b)
 fmt.Printf("Test1 name:%s\n", b.Name)
 b.Name = "john"
}
func(b *B) Test2() {
 fmt.Printf("Test2 addr:%p\n", b)
 fmt.Printf("Test2 name:%s\n", b.Name)
 b.Name = "john"
}
func main() {
 b := B{}
 b.Test1()
 b.Test1()
 b.Test2()
 b.Test2()
}

The results after execution are as follows:


Test1 addr:0xc42000e1e0
Test1 name:
Test1 addr:0xc42000e1f0
Test1 name:
Test2 addr:0xc42000e1d0
Test2 name:
Test2 addr:0xc42000e1d0
Test2 name:john

Can see Test1 address of the printer b structure in the changes, and there is no change in Test2, that means every one Test1 calls, are introduced to the structure of the body b 1 copy (copies), when the internal variables in Test1 any changes, will fail (because the one time I visit the incoming is b structure new copy). When the Test2 method is passed as a pointer, every time it passes in a pointer to the same structure, so the address does not change, and when the internal variable is changed, it is the changed b structure.

This difference in Go may be a pit in OOP's design. To implement OOP's design in Go, the method encapsulation method is Test2.

conclusion


Related articles: