问题提要
之前写代码的时候遇到了一个问题:自己编写了一个接口,然后又写了一个结构体实现这个接口,在通过函数调用接口方法时出现了问题。
代码如下:
type Validator interface {
Valid() bool
}
type LoginInput struct {
Username string
Password string
}
func (input *LoginInput) Valid() bool {
// 一些检验逻辑
// 返回校验结果
}
func Handle(v Validator) {
res := v.Valid()
// 根据校验结果做一些逻辑处理
}
func main() {
// 对具体过程做了提炼,最终逻辑一致
input := LoginInput{Username: "XXX", Password: "YYY"}
Handle(input)
}
mainHandle()GolandCannot use 'input' (type LoginInput) as type ValidatorType does not implement 'Validator' as 'Valid' method has a pointer receiver
Handle()Handle(&input)
方法集
什么是方法集
我们先来看看Golang官方对它的描述:
总结一下官方文档表述的意思,我们得到如下一张表:
变量类型 | 方法接收器类型 |
---|---|
T | (t T) |
*T | (t T) + (t *T) |
TT*TT*TLoginInputnotify
结构体的方法调用与方法集之间的关系
其实到这里就会有个疑问:平时调用方法时,无论变量类型是值类型还是指针类型都能调用成功,也没出过问题啊。
这里其实是Golang的一个语法糖:在使用选择器(Selectors)调用方法时,编译器会帮你做好取址或取值的操作的。
下面通过代码说明一下这个关系:
type StructA struct {}
func (s StructA) ValueReceiver () {}
func (s *StructA) PointReceiver () {}
func main() {
value := StructA{}
point := &value
// 编译器不做处理,就是value.ValueReceiver()
value.ValueReceiver()
// 其实是(&value).ValueReceiver()的简便写法
value.PointReceiver()
// 其实是(*point).ValueReceiver()的简便写法
point.ValueReceiver()
// 编译器不做处理,就是point.ValueReceiver()
point.PointReceiver()
}