golang接口中方法集的运行机制


package main

import(
    "fmt"
)
//通知行为的接口
type notifier interface{
    notify()
}
//自定义的用户类型
type user struct{
    name string
    email string 
}
//notify是用指针接收者实现的方法
func (u *user ) notify(){
    fmt.Println(u)
}

func main(){
    u:= user{"lp","344085057@qq.com"}
    sendNotification(u)
}
//sendNotification 接受一个实现了notifier接口的值
func sendNotification(n notifier){
    n.notify()
}
运行结果:

cannot use u (type user) as type notifier in argument to sendNotification:
user does not implement notifier (notify method has pointer receiver)

翻译

无法在sendNotification的参数中使用u(type user)类型:
user未实现sendNotification(notify方法具有指针接收器)

原因

//因为这里 只有指向user的指针才能够实现对应的接口。
sendNotification(u)

//正确的调用姿势
sendNotification(&u)

让我们来了解go语言规范里定义的方法集的规则:

从值的角度看这些规则:

Values           Methods Receivers
————————————————————————————
T                      (t T)
*T                    (t T) or (t *T)
描述:

T类型的值的方法集只包含值接收者申明的方法。
*T(T类型的指针) 类型的指针的方法集即包含值接收者申明的方法,也包含指针接收者声明的方法。

从接收者类型的角度来看这些规则:

 Methods Receivers       Values          
————————————————————————————
(t T)                                          T
(t T) or (t *T)                       *T
描述:

如果使用指针接收者来实现一个接口,那么只有指向那个类型的指针才能够实现对应的接口。
如果使用值接收者来实现一个接口,那么那个类型的值和指针都能够实现对应的接口