【注意】最后更新于 December 2, 2019,文中内容可能已过时,请谨慎使用。
对 interface 赋值变量的时候经常出的问题
日常开发时有个这样的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
package main
import "fmt"
type Human interface {
Run()
}
type Boy struct {
Name string
}
func (b *Boy) Run() {
fmt.Println("my name is " + b.Name)
}
func main() {
xiaoming := Boy{Name: "xiao ming"}
var h Human
// h = xiaoming // #1 会报错, Boy does not implement Human (Run method has pointer receiver)
h = &xiaoming
h.Run()
}
|
如果用 #1
这行代码时会出现以下错误:
1
2
3
|
# command-line-arguments
./main.go:23:4: cannot use xiaoming (type Boy) as type Human in assignment:
Boy does not implement Human (Run method has pointer receiver)
|
然而用下面的 h = &xiaoming
是正常的
这个问题,首先得先了解一下Golang 中 方法的集合的概念,一个struct虽然可以通过值类型和引用类型两种方式定义方法,但是不通的对象类型对应了不同的方法集:
1
2
3
4
|
Values Methods Receivers
-----------------------------------------------
T (t T)
*T (t T) and (t *T)
|
值类型的对象只有(t T) 结构的方法,虽然值类型的对象也可以调用(t *T) 方法,但这实际上是Golang编译器自动转化成了&t的形式来调用方法,并不是表明值类型的对象拥有该方法。
换一个维度来看上面的表格可能更加直观:
1
2
3
4
5
|
Methods Receivers Values
-----------------------------------------------
(t T) T and *T
(t *T) *T
|
这就意味着指针类型的receiver 方法实现接口时,只有指针类型的对象实现了该接口。
对应上面的例子来说,只有&user实现了notifier接口,而user根本没有实现该接口。所以上面代码会报出这样的异常。
文章作者
GPF
上次更新
2019-12-02
(521dbfe)