go里c *Gopher(对象的指针)和c Gopher(纯粹对象自己)对应方法集不同(其他语言是同一个类型,java,python,c,c++等,所以方法集自然相同)
对应案例 | 调用方 | 接收方 | 修改效果 |
---|---|---|---|
1、使用值调用 | 对象+值(纯粹对象) | 注册到值的方法(这里是 code()) | 不改动原始取值 |
2、使用指针调用 | 对象+指针 | ||
3、使用interface作为调用者 | interface+指针型 | 注册到指针的方法(这里是 debug()) | 改动原始取值 |
4、使用interface作为调用者 | interface+值类型 |
以上table从接收者视角:值接收者声明的方法能接受值类型和指针类型的参数,指针接收者声明的方法只能接受指针类型的参数。
这一点很容易搞错,比如这篇文章中的举例就是错误的。
典型错误文章,go语言学习:方法:https://blog.csdn.net/weixin_44202489/article/details/105537011
第三部分,三、方法集,中的样例代码都是错误的,(结论对的,样例代码错了)
针对的是上表的第一二种情况。
将文中:类型 *T 方法集包含全部 receiver T + *T 方法。
样例代码:
1 | func main() { |
改为
1 | func main() { |
也可正常执行,所以可以得到结论:类型 T 方法集包含全部 receiver T + *T 方法?
显然不对了。
案例 | 现象 | 结论 |
---|---|---|
1、使用值调用 | debug方法成功修改了num的取值,而code没有 | 由值作为接收者,被调用时,是对对象的拷贝,指针作为接收者,被调用时,是对对象本身的操作。 |
2、使用指针调用,结合案例1、使用值调用 | 可正常运行且输出结果和第一段代码一样 | 不管方法的接收者是什么类型,该类型的值和指针都可以调用,不必严格符合接收者的类型。(案例1和2的调用者Gopher和*Gopher,都属于具体的静态的类型) |
3、使用interface作为调用者(interface+指针型) | 正常编译,输出 | 同上 |
3、使用interface作为调用者结合 案例4、使用interface作为调用者 | 无法编译 | interface+值类型,会丧失一部分方法,丧失一部分:注册到指针的方法 |
参考
go语言结构体定义方法时,值作为接收者和指针作为接收者的区别:https://blog.csdn.net/u014239709/article/details/89552933