一个和 go 断言有关的神奇写法

2019-05-28 19:01:43 +08:00
 gramyang

self := &tcpSession{ conn: conn, endNotify: endNotify, sendQueue: cellnet.NewPipe(), pInterface: p, CoreProcBundle: p.(interface { GetBundle() *peer.CoreProcBundle }).GetBundle(), }

这是 cellnet 源码里的一段,位置是 cellnet/peer/tcp/session.go 里的 newSession。 p 是一个接口,其实现类 tcpSession 里面有一个内嵌结构体就是 peer.CoreProcBundle,peer.CoreProcBundle 有一个方法 GetBundle()。 这段代码看起来像是 p 接口断言,但是匿名接口里的方法只是 p 的子类的一个内嵌结构体的方法而已啊。。

搞不懂,求高手指导

3578 次点击
所在节点    Go 编程语言
13 条回复
whoami9894
2019-05-28 19:24:34 +08:00
tcpSession 是 interface p 的实现类 && tcpSession 内嵌了匿名 peer.CoreProcBundle
=> tcpSession 有 GetBundle 方法
=> interface p 有 GetBundle 方法
=> p 断言这个字面量类型会成功`interface { GetBundle() *peer.CoreProcBundle }`
whoami9894
2019-05-28 19:26:36 +08:00
@whoami9894
通过断言转换到`interface { GetBundle() *peer.CoreProcBundle }`并调用 GetBundle
icexin
2019-05-28 19:40:44 +08:00
断言到一个匿名接口
gramyang
2019-05-28 19:57:12 +08:00
@whoami9894。。但是 p 并没有 GetBundle 方法啊
liulaomo
2019-05-28 20:09:17 +08:00
@gramyang
p 虽没有 GetBundle 方法,但是它此时的动态值有此方法即可。
详见: https://gfw.go101.org/article/interface.html#reflection

出现这种写法一般属于设计上没做好,但有需要一定时间才能完善的暂时之举。
gramyang
2019-05-28 20:11:19 +08:00
@liulaomo 链接打不开啊,另外动态值怎么说来着?
whoami9894
2019-05-28 20:22:35 +08:00
@gramyang
interface 就是个抽象类型,假如这里 p 是 tcpSession 的话它就实现了 getBundle,这里就在做类型断言来确定有没有这个方法
gramyang
2019-05-28 20:28:30 +08:00
@whoami9894 我大概明白你的意思了,tcpSession 确实是有 getBundle 方法的,只不过是 tcpSession 的内嵌结构体 CoreProcBundle 有 getBundle 方法,当然这也算 tcpSession 持有这个方法。这里相当于 tcpSession 转换为它的内嵌结构体 CoreProcBundle
liulaomo
2019-05-28 20:50:09 +08:00
看代码,这里的 p 只能是一个*tcpSyncConnector 或者*tcpConnector 类型的值,而这两个类型都内嵌了 peer.CoreProcBundle。peer.CoreProcBundle 是有 GetBundle() *CoreProcBundle 这个方法的。所以此类型断言是不会 panic 的。
liulaomo
2019-05-28 20:51:37 +08:00
@gramyang
在线版打不开的话,可以浏览本地版: https://github.com/golang101/golang101
gramyang
2019-05-28 21:09:12 +08:00
@liulaomo 我的天!突然冒出来一位野生大神传授我一本自己写的书!感谢分享!!
acehow
2019-05-28 21:35:25 +08:00
@gramyang 他是无崖子,传功给你这个虚竹。为的是你可以和段誉萧峰一起协助我大宋,抵抗川普的贸易战攻击。
tairan2006
2019-05-29 09:13:13 +08:00
这种一般都是设计有问题

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/568504

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX