关于接收者的问题
来源:6-4 接口的值类型

杰瑞大杰瑞
2020-11-21
老师您好,这节看了几遍,但是还是没有理解接收者的概念。如果单纯看代码规则,可以大概理解,但是听了相关解释和报错信息,反而对不上号了。
- 什么是接收者?
比如下面,我可以理解成为,一个Retriever的类,如果在下面添加一些特殊的函数(函数名前面加上(r *Retriever),就相当于这个函数与类绑定了,属于Retriever的方法,但是(r *Retriever)称之为“接收者”,就不太明白了,程序执行过程中,哪里体现了接收的含义呢?是谁接收?
type Retriever struct {
Contents string
}
func (r *Retriever) Post(url string,
form map[string]string) string {
r.Contents = form["contents"]
return "ok"
}
func (r *Retriever) Get(url string) string {
return r.Contents
}
- 指针接收?
1) 将r = &mockRetriever的地址符号去掉后,会报错:
Cannot use ‘mockRetriever’ (type "imooc.com/ccmouse/learngo/lang/retriever/mock".Retriever) as type “imooc.com/ccmouse/learngo/lang/retriever”.Retriever
Type does not implement ‘Retriever’ as ‘Get’ method has a pointer receiver
其实也可以理解,这里去掉地址符没有符合方法里面指针接受者的定义,为什么说因为Get方法是指针接受者,所以这里并没有实现Retriver?感觉这前后没有关系呢?
2) 另外,保持r = mockRetriever不更改,我将mock.Retriever里面的Get接受者还原回值接受者,没有报错了,但是我看上面的Post函数的接受者还是指针接受者,这个情况下,为什么不报’Post’ method has a pointer receiver的错误呢?
谢谢。
1回答
-
ccmouse
2020-11-23
这一节确实牵涉了部分实现细节。
什么是接收者?
接收者就是这种用(r *Retriever)括起来的参数。“接收者”只是一个说法。别的语言会有隐示的this、或者self,那go语言要我们显示的写出来,这里的r我们就叫接收者。实际上并没有接收数据,只是这个struct接收了这个方法(Get函数,或者Post函数)。
关于指针接收者。
"这个情况下,为什么不报’Post’ method has a pointer receiver的错误呢?"这里有一个语法糖。标准的写法应该是(*mock).Post。但这样很啰嗦,所以go语言给了我们一个语法糖,让我们可以写成mock.Post,编译器会自动帮我们转成(*mock).Post。
而在“将r = &mockRetriever的地址符号去掉后“,这边,编译器并没有给我们语法糖,所以,我们这个Get方法的接收者是*mockRetriever,只有*mockRetriever上才有Get方法。所以实现Retriever接口的类型是*mockRetriever,而不是mockRetriever。这也是为什么他说mockRetriever没有实现Retriever接口。
那么最后可能会想,为什么语法糖没有全都给呢?是因为一个复杂的权衡,mock.Post要比(*mock).Post简洁很多,所以go语言特别做了支持。
而r=&mockRetriever和r=mockRetriever,并没有代码简洁度上的区别,所以go语言要求我们明确这是指针还是值。
10
相似问题
回答 1
回答 1