浅谈Golang T和*T方法集的关系
四种调用场景
接口传值,调用值接收者
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 是两种不同的类型!