Golang method receiver type 的差異

在 Go 裡,method 的 receiver 是用 *Obj 還是用 Obj 會有不同的行為。

來個例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
type Vertex struct {
X, Y float64
}

func (v Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func (v Vertex) moveX(movement float64) {
v.X += movement
}

func (v *Vertex) moveY(movement float64) {
v.Y += movement
}

func main() {
v := Vertex{X: 10, Y: 20}

log.Println(v.X, v.Y, v.Abs()) // 10 20 22.360679774997898

v.moveX(2)
log.Println(v.X, v.Y, v.Abs()) // 10 20 22.360679774997898

v.moveY(3)
log.Println(v.X, v.Y, v.Abs()) // 10 23 25.079872407968907
}

v 可以看成像參數。

Vertex 就是 copy by value,caller 跟 callee 的 Vertex instance 是不同的。

*Vertex 就像 C 語言 pointer 參數,本質上還是 copy by value 但因為是 pointer,所以在 moveY() 中的 v 變成是指向 caller 的那個 Vertex instance。

基本上 method 會動到 struct 內的 field 內容都會用 pointer。習慣上當有一個 method 的 receiver 是用 pointer 時,所有 method 的 receiver 都會用 pointer。