四种调用场景
接口传值,调用值接收者
package main type Iface interface { hello() } type Stu struct { } func (c Stu) hello() { panic("implement me") } func main(){ var IfTs Iface var stu Stu IfTs=stu IfTs.hello() }
接口传指针,调用指针接收者
package main type Iface interface { hello() } type Stu struct { } func (c *Stu) hello() { panic("implement me") } func main(){ var IfTs Iface var stu Stu IfTs=&stu IfTs.hello() }
接口传指针,调用值接收者(success)
package main type Iface interface { hello() } type Stu struct { } func (c Stu) hello() { panic("implement me") } func main(){ var IfTs Iface var stu Stu IfTs=&stu IfTs.hello() }
接口传值,调用指针接收者(error)
package main type Iface interface { hello() } type Stu struct { } func (c *Stu) hello() { panic("implement me") } func main(){ var IfTs Iface var stu Stu IfTs=stu//err IfTs.hello() }
原因剖析
首先要明确一点,T和*T是两种不同的类型。
那为什么第三种情况可以正常运行呢?通过*T类型的变量调用T类型的接收者的方法,只是一种语法糖,编译器会在调用端进行指针解引用。
那为什么第四种情况会err呢?因为*T和T是两种不同的类型,这里没有语法糖,T类型没有实现接口的方法,自然会err咯。无法将’stu’ (类型Stu)用作类型Iface类型,未实现’Iface’
总结
因为通过 *T 类型的变量调用T类型的接收者的方法,是一种语法糖,所以可以简单的理解为 *T 的方法集包括了所有的T方法集,这也就是为什么会有人说,只要接收者里面有一个是指针接收者,那就把所有的方法接收者都改为指针接收者的原因了。不过需要注意的是T和 *T 是两种不同的类型!