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 的子类的一个内嵌结构体的方法而已啊。。
搞不懂,求高手指导
1
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 }` |
2
whoami9894 2019-05-28 19:26:36 +08:00
@whoami9894
通过断言转换到`interface { GetBundle() *peer.CoreProcBundle }`并调用 GetBundle |
3
icexin 2019-05-28 19:40:44 +08:00
断言到一个匿名接口
|
4
gramyang OP @whoami9894。。但是 p 并没有 GetBundle 方法啊
|
5
liulaomo 2019-05-28 20:09:17 +08:00
@gramyang
p 虽没有 GetBundle 方法,但是它此时的动态值有此方法即可。 详见: https://gfw.go101.org/article/interface.html#reflection 出现这种写法一般属于设计上没做好,但有需要一定时间才能完善的暂时之举。 |
7
whoami9894 2019-05-28 20:22:35 +08:00 via Android
@gramyang
interface 就是个抽象类型,假如这里 p 是 tcpSession 的话它就实现了 getBundle,这里就在做类型断言来确定有没有这个方法 |
8
gramyang OP @whoami9894 我大概明白你的意思了,tcpSession 确实是有 getBundle 方法的,只不过是 tcpSession 的内嵌结构体 CoreProcBundle 有 getBundle 方法,当然这也算 tcpSession 持有这个方法。这里相当于 tcpSession 转换为它的内嵌结构体 CoreProcBundle
|
9
liulaomo 2019-05-28 20:50:09 +08:00
看代码,这里的 p 只能是一个*tcpSyncConnector 或者*tcpConnector 类型的值,而这两个类型都内嵌了 peer.CoreProcBundle。peer.CoreProcBundle 是有 GetBundle() *CoreProcBundle 这个方法的。所以此类型断言是不会 panic 的。
|
10
liulaomo 2019-05-28 20:51:37 +08:00
|
12
acehow 2019-05-28 21:35:25 +08:00 via Android
@gramyang 他是无崖子,传功给你这个虚竹。为的是你可以和段誉萧峰一起协助我大宋,抵抗川普的贸易战攻击。
|
13
tairan2006 2019-05-29 09:13:13 +08:00 via Android
这种一般都是设计有问题
|