Appearance
Go 值接收器方法 vs 指针接收器方法
使用值接收器的方法可以通过值或指针调用,而使用指针接收器的方法只能通过指针或可寻址值调用;
Gotype S struct { data string } func (s S) Read() string { return s.data } func (s *S) Write(str string) { s.data = str } sVals := map[int]S{1: {"A"}} // 你通过值只能调用 Read sVals[1].Read() // 这不能编译通过: // sVals[1].Write("test") sPtrs := map[int]*S{1: {"A"}} // 通过指针既可以调用 Read,也可以调用 Write 方法 sPtrs[1].Read() sPtrs[1].Write("test")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即使方法是值接收器,该对象的指针也能满足接口;
Gotype F interface { f() } type S1 struct{} func (s S1) f() {} type S2 struct{} func (s *S2) f() {} s1Val := S1{} s1Ptr := &S1{} s2Val := S2{} s2Ptr := &S2{} var i F i = s1Val i = s1Ptr i = s2Ptr // 下面代码无法通过编译。因为 s2Val 是一个值,而 S2 的 f 方法中没有使用值接收器 // i = s2Val1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
关于以上两点我们可以这样理解:一个类型可以有值方法集和指针方法集,指针方法集包含值方法集(值接收器的方法同时包于指针方法集和值方法集)。
- 值对象只可以使用值方法集,指针对象可以使用值方法集和指针方法集;
- 当值方法集和接口匹配时,不管是值还是指针对象都可以赋值给接口,而当只有指针方法集和接口匹配时,那么只有指针可以赋值给接口;
Effective Go 中有一段关于 pointers vs. values 的精彩讲解。