来自公众号:新世界杂货铺

作为一个长期从事Go语言开发的程序猿,笔者不敢说自己是老油条但也勉强算一个小油条。然而就在今天,笔者研究TLS/SSL握手源码的时候,突然灵光一闪,想到了一个和自己认知不符的现象,于是赶紧写了一个例子验证一番,结果当头一棒直到码这篇文章时依旧懵逼。

话不多说,上锤!

不好意思,不是这个锤,是下面这个:

type set interface {set1(s string)set2(s string)
}
type test struct {s string
}
func (t *test) set1(s string) {t.s = s
}
func (t test) set2(s string) {t.s = s
}
func main() {var (t1 testt2 = new(test))t1.set1("1")fmt.Print(t1.s)t1.set2("2")fmt.Print(t1.s)t2.set1("3")fmt.Print(t2.s)t2.set2("4")fmt.Print(t2.s)fmt.Print(" ")_, ok1 := (interface{}(t1)).(set)_, ok2 := (interface{}(t2)).(set)fmt.Println(ok1, ok2)
}

正确答案笔者就不直接公布了,请各位读者耐心在后文寻找答案。

方法集

根据golang官方文档知道,一个类型有一个与之关联的方法集。接口类型的方法集是接口中定义的方法。

官方文档中特别提到,类型T的方法集包含用T声明为Receiver的所有方法,而指针类型*T的方法集包含用T和*T声明的所有方法。

此时,我们回到上面的例子可以很明显的知道下面这段代码输出为false true

_, ok1 := (interface{}(t1)).(set)
_, ok2 := (interface{}(t2)).(set)
fmt.Println(ok1, ok2)

T类型的方法集不包含*T类型的方法集,因此t1无法转为set接口类型。

事实上,根据这部分官方文档笔者更加疑惑了,因为上述例子可以正常运行,而且类型为test的变量调用了(*test).set1方法。抱着这样的疑惑笔者疯狂谷狗,最后在stackoverflow的指导下发现了这种情况和方法调用有关。

这里特别感谢一下谷狗和stackoverflow。

方法调用

方法调用笔者在这里仅说明和本篇相关的内容,其他细节相信各位读者都已经了然于胸。

下面,先看看官方文档原文:

A method call x.m() is valid if the method set of (the type of) x contains m and the argument list can be assigned to the parameter list of m. If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m()

简单来说,如果x可寻址,且&x的方法集包含m,则x.m()(&x).m的缩写。这样前面的例子能够正常运行也在情理之中了。

因此,前面例子的最终输出结果是:1133 false true

如果读者对结构体中的值未发生改变有疑惑,请参考笔者的这篇文章——为什么go中的receiver name不推荐使用this或者self。

你以为你都懂了

写完前面的方法集和方法调用笔者细细思考一番,确认没有其他遗漏的细节,于是放心的上了个厕所。结果厕所还没上完,立马想到一个问题(额外多扯一句,笔者经常在上厕所的时候找到灵感,这可能就是劳逸结合的最佳实践吧):

type los stringfunc (s los) p1() {fmt.Println(s)
}func (s *los) p2() {fmt.Println(s)
}func main() {var s1 los = "1111"var s2 *los = &s1const s3 los = "3333"s1.p1()s1.p2()s2.p1()s2.p2()s3.p1()s3.p2()
}

如果你对上面的代码没有任何疑问且认为上述代码能够正常运行,那只能说明你对本文的阅读还不够认真。

我们先看看上述代码在vscode中的报错。

前面介绍方法调用时,如果x可寻址,则x可以调用&x的类型的方法集。上述代码s3是常量,是不可以寻址的,因此无法调用(*los).p2方法。

以上,就是笔者曾经忽略的细节,现在回过头来看一看倒也充满了乐趣。

彩蛋

本篇是研究TLS/SSL握手流程的副产品,因为TLS/SSL握手流程笔者还在整理中,故这篇文章先行一步给个预告,下一期TLS/SSL握手流程敬请期待。

最后,衷心希望本文能够对各位读者有一定的帮助。

注: 1. 写本文时, 笔者所用go版本为: go1.15.2 2. 文章中所用完整例子:https://github.com/Isites/go-coder/blob/master/receiver/main.go

参考

https://golang.org/ref/spec#Method_sets

https://golang.org/ref/spec#Calls

js 调用另一个类的方法_一个隐藏在方法集和方法调用中且易被忽略的小细节相关推荐

  1. 安卓一个方法多处调用_一个隐藏在方法集和方法调用中且易被忽略的小细节

    来自公众号:新世界杂货铺 作为一个长期从事Go语言开发的程序猿,笔者不敢说自己是老油条但也勉强算一个小油条.然而就在今天,笔者研究TLS/SSL握手源码的时候,突然灵光一闪,想到了一个和自己认知不符的 ...

  2. 设计一个类代表二维空间的一个点,设计一个类代表二维空间的一个圆。要求两个成员变量。一个是圆心,一 个是半径,提供计算面积的方法。为上述Cricle类添加一个方法,计算一个点(Point)是否在圆内

    (1) 设计一个类代表二维空间的一个点 (2) 设计一个类代表二维空间的一个圆.要求两个成员变量.一个是圆心,一 个是半径,提供计算面积的方法. (3) 为上述Cricle类添加一个方法,计算一个点( ...

  3. Java设计一个类代表二维空间的一个点,设计一个类代表二维空间的一个圆,计算面积,,并写程序验证计算一个点(Point对象)是否在圆(Cricle对象)内

    题目要求: (1) 设计一个类代表二维空间的一个点 (2) 设计一个类代表二维空间的一个圆.要求两个成员变量.一个是圆心,一 个是半径,提供计算面积的方法. (3) 为上述Cricle类添加一个方法, ...

  4. 京东商智--POP店铺数据导出(每一个类目,每一个月份的数据)--本次为了汇总2019年度数据

    dim arrayRet = "" dim objExcelWorkBook = "" dim hWeb = "" dim sRet = & ...

  5. js ios调用ios方法_通过iOS 13的模式演示调用生命周期方法

    js ios调用ios方法 iOS 13 was legendary iOS 13传奇 iOS 13 brought many cool things; dark mode, sign in with ...

  6. C# 子类实例化基类 基类使用不了子类的方法_老话题:6个方法,检验你有没有正确使用设计模式...

    方法一:设计模式是为了消除继承 大部分设计模式,是让你在在面向对象的基础上尽量消除继承的手段.所以,如果你用了一些设计模式,减少了继承,那你八成用对了.如果你用了一大堆设计模式,然而继承却越来越频繁, ...

  7. java 异步调用方法_乐字节Java编程之方法、调用、重载、递归

    一.概述 方法是指人们在实践过程中为达到一定目的和效果所采取的办法.手段和解决方案. 所谓方法,就是解决一类问题的代码的有序组合,是一个功能模块.编程语言中的方法是组合在一起来执行操作语句的集合.例如 ...

  8. 一个java类可以有_一个.java文件中可以有几个同级类?

    1.在一个.java文件中可以有多个同级类(和public一样的位置,注意不是内部类).其修饰符只可以public/abstract/final/和无修饰符,不能是其他的protected/priva ...

  9. pygame显示图片的方法_使用Sprite实现移动动画(Pygame中的精灵类)

    pygame.sprite.Sprite就是Pygame里面用来实现精灵的一个类,使用时,并不需要对它实例化,只需要继承他,然后按需写出自己的类就好了,因此非常简单实用. 什么是精灵? 精灵可以认为成 ...

最新文章

  1. DockPanel Suite 开源WINFORM 窗体停靠面板控件
  2. 机房冒水导致1500万元研发的源代码消失,软件公司起诉物业索赔七百万
  3. OData model cache logic in gateway system
  4. LQ训练营(C++)学习笔记_背包问题
  5. 基于TextRank算法的文本摘要(附Python代码)
  6. SmartPhone和PPC手机的区别
  7. 重庆声光电安全预警平台项目启动会顺利召开
  8. ENVI5.3.1 去除影像四周的黑色背景
  9. 浏览器主页被劫持篡改为hao123或者别的网页解决方法
  10. 周金涛:繁荣的起点并非沸腾的年代,或将在2020年出现首次证券市场大繁荣
  11. 机器学习高阶理论知识列表
  12. android 家谱,Desire竟垫底 独家曝光Android手机家谱
  13. android 实现浮动窗口,轻松实现类VC界面浮动窗口(转载)
  14. 计算机体系复习(三)
  15. Jmeter多线程并发和压测结果分析
  16. iphone同步android短信恢复,用什么软件可以将安卓的短信恢复到苹果中
  17. 鸿蒙(HarmonyOS)2.0方舟编译器官方网址开源地址
  18. 【计算机毕业设计】001基于SpringBoot的在线拍卖系统
  19. 24种页面元素与iDo网页设计工具箱
  20. oracle上机题库_oracle考试题库

热门文章

  1. linux拷贝大量文件时有什么方法可以效验文件有没有损坏,使用linux的cp命令复制文件后验证文件是否一致的方法...
  2. 每日程序C语言42-带头结点的尾插法创建链表
  3. switch java 语法_Java编程—switch语句语法详解
  4. 2010年杭电计算机研究生复试---笔试编程
  5. 阿里云服务器CentOS6.9安装jenkins
  6. Python爬虫的开发
  7. Spring Caching集成Ehcache
  8. jQuery event的复制粘贴的坑
  9. mootools系列:打造属于你自己的Popup(弹出框)——扩展功能篇
  10. 判断输入的数是否质数,求范围内的质数有哪些