Golang Go语言中一个和断言有关的神奇写法
Golang Go语言中一个和断言有关的神奇写法
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 的子类的一个内嵌结构体的方法而已啊。。
搞不懂,求高手指导
更多关于Golang Go语言中一个和断言有关的神奇写法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
通过断言转换到interface { GetBundle() *peer.CoreProcBundle }
并调用 GetBundle
断言到一个匿名接口
。。但是 p 并没有 GetBundle 方法啊
p 虽没有 GetBundle 方法,但是它此时的动态值有此方法即可。
详见: https://gfw.go101.org/article/interface.html#reflection
出现这种写法一般属于设计上没做好,但有需要一定时间才能完善的暂时之举。
链接打不开啊,另外动态值怎么说来着?
interface 就是个抽象类型,假如这里 p 是 tcpSession 的话它就实现了 getBundle,这里就在做类型断言来确定有没有这个方法
我大概明白你的意思了,tcpSession 确实是有 getBundle 方法的,只不过是 tcpSession 的内嵌结构体 CoreProcBundle 有 getBundle 方法,当然这也算 tcpSession 持有这个方法。这里相当于 tcpSession 转换为它的内嵌结构体 CoreProcBundle
看代码,这里的 p 只能是一个tcpSyncConnector 或者tcpConnector 类型的值,而这两个类型都内嵌了 peer.CoreProcBundle。peer.CoreProcBundle 是有 GetBundle() *CoreProcBundle 这个方法的。所以此类型断言是不会 panic 的。
在线版打不开的话,可以浏览本地版: https://github.com/golang101/golang101
我的天!突然冒出来一位野生大神传授我一本自己写的书!感谢分享!!
他是无崖子,传功给你这个虚竹。为的是你可以和段誉萧峰一起协助我大宋,抵抗川普的贸易战攻击。
这种一般都是设计有问题
在Go语言中,断言(type assertion)是一种用于检查接口值动态类型并在需要时进行类型转换的强大机制。虽然Go语言本身没有提供所谓的“神奇写法”来直接增强断言的功能,但通过一些惯用法和技巧,我们可以实现更加优雅和安全的断言处理。
一个常见的技巧是使用Go 1.18引入的类型参数(Generics)和类型断言的结合,来编写更加通用的代码。然而,由于类型参数本身并不直接支持断言,这种结合更多是在设计算法或数据结构时提供额外的灵活性。
在实际编码中,一个更“神奇”的写法可能是利用Go的短变量声明和多重返回值特性,来简洁地处理断言失败的情况。例如:
var i interface{} = "hello"
// 使用类型断言,同时处理失败情况
if s, ok := i.(string); ok {
fmt.Println(s) // 输出:hello
} else {
fmt.Println("类型断言失败")
}
在这个例子中,i.(string)
尝试将i
断言为string
类型。如果成功,s
将包含断言后的值,ok
将为true
;如果失败,ok
将为false
,并且可以在else
分支中处理失败的情况。
总的来说,虽然Go语言没有提供直接的“神奇写法”来增强断言,但通过结合使用Go的内置特性和惯用法,我们可以编写出既简洁又强大的代码来处理类型断言。