首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
beego
V2EX  ›  Go

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

  •  1
     
  •   gramyang · 56 天前 · 1698 次点击
    这是一个创建于 56 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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 条附言  ·  56 天前
    现在我只能这么理解:
    假如一个结构体 a 和其他的结构体共同实现了一个接口 p,那么这个接口是不能准确的指代这个结构体的。

    而这个结构体 a 有自己的方法 function1,那么 p.(interface {function1})可以转型为 a,即这个 interface {function1}的匿名接口可以指代 a。
    13 回复  |  直到 2019-05-29 09:13:13 +08:00
        1
    whoami9894   56 天前
    tcpSession 是 interface p 的实现类 && tcpSession 内嵌了匿名 peer.CoreProcBundle
    => tcpSession 有 GetBundle 方法
    => interface p 有 GetBundle 方法
    => p 断言这个字面量类型会成功`interface { GetBundle() *peer.CoreProcBundle }`
        2
    whoami9894   56 天前
    @whoami9894
    通过断言转换到`interface { GetBundle() *peer.CoreProcBundle }`并调用 GetBundle
        3
    icexin   56 天前
    断言到一个匿名接口
        4
    gramyang   56 天前
    @whoami9894。。但是 p 并没有 GetBundle 方法啊
        5
    liulaomo   56 天前
    @gramyang
    p 虽没有 GetBundle 方法,但是它此时的动态值有此方法即可。
    详见: https://gfw.go101.org/article/interface.html#reflection

    出现这种写法一般属于设计上没做好,但有需要一定时间才能完善的暂时之举。
        6
    gramyang   56 天前
    @liulaomo 链接打不开啊,另外动态值怎么说来着?
        7
    whoami9894   56 天前 via Android
    @gramyang
    interface 就是个抽象类型,假如这里 p 是 tcpSession 的话它就实现了 getBundle,这里就在做类型断言来确定有没有这个方法
        8
    gramyang   56 天前
    @whoami9894 我大概明白你的意思了,tcpSession 确实是有 getBundle 方法的,只不过是 tcpSession 的内嵌结构体 CoreProcBundle 有 getBundle 方法,当然这也算 tcpSession 持有这个方法。这里相当于 tcpSession 转换为它的内嵌结构体 CoreProcBundle
        9
    liulaomo   56 天前
    看代码,这里的 p 只能是一个*tcpSyncConnector 或者*tcpConnector 类型的值,而这两个类型都内嵌了 peer.CoreProcBundle。peer.CoreProcBundle 是有 GetBundle() *CoreProcBundle 这个方法的。所以此类型断言是不会 panic 的。
        10
    liulaomo   56 天前
    @gramyang
    在线版打不开的话,可以浏览本地版: https://github.com/golang101/golang101
        11
    gramyang   56 天前
    @liulaomo 我的天!突然冒出来一位野生大神传授我一本自己写的书!感谢分享!!
        12
    acehow   56 天前 via Android
    @gramyang 他是无崖子,传功给你这个虚竹。为的是你可以和段誉萧峰一起协助我大宋,抵抗川普的贸易战攻击。
        13
    tairan2006   55 天前 via Android
    这种一般都是设计有问题
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2064 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 19ms · UTC 00:25 · PVG 08:25 · LAX 17:25 · JFK 20:25
    ♥ Do have faith in what you're doing.