Go1.23 新特性:试图禁用 //go:linkname,建立新的握手机制!

大家好,我是煎鱼。

Go1.23 的新版本特性中,还有一些声势浩大的变更,引发了社区的一些争议和讨论。

今天主要给大家分享 //go:linkname 变更的前因后果和新特性。

背景

在今年 5 月份,rsc 不知道是看到了什么项目在乱搞什么骚操作,触发了他的 "逆鳞"。直接反手光速敲出了以下提案:

他发现的问题是:目前存在过度使用 //go:linkname 来深入 Go 标准库内部(尤其用在 runtime 内部)的场景。

这意味着当 Go 官方团队以正常的设计迭代去更改 Go 标准库内部时,最终有可能会关联地破坏 Go 生态系统中大量依赖的软件包。因为 Go "家里" 很多东西都被外部社区依赖了。

例如像是在该项 CL 修改:internal/reflectlite: remove redundent ifaceIndir 破坏了 github.com/goccy/go-json 库的引用:

最终事实证明该库复制了 runtime 的大部分内部类型 API。现在倒逼的 Go 团队无法更改该 CL 中的任何内容。(煎鱼:许多包都使用 goccy,包括 Kubernetes。意思是很重要,有 KA 大客户在用)

自我解释

很多同学看到这个提案要封杀 //go:linkname 的用法后,纷纷吐槽:"Go 团队自己也会用,Go 源码里一大堆这么用的。这不是典中典吗?"

为此 rsc 对此也给出了对应的解释:这种使用内部类型的情况是不可持续的!

内部是内部的,这么用是有原因的。当用户的 Go 程序对我们保留在内部的细节产生显式依赖时,我们无法让它们继续运行。

但我们也非常关心兼容性:我们也不想破坏 Go 程序。显而易见的结论是:必须首先阻止 Go 程序能够对内部细节产生这些依赖。

Go1.23 //go:linkname 的改变

改进计划

理想的目标状态是:所有 //go:linkname 用法都必须采用握手(Handshake)的方式/机制,也就是:双方必须同意使用给定符号的 linkname 才能成功。(煎鱼:但也知道已经无法如此圆满了)

Go1.23 新版本起的新机制(计划)如下:

  1. 加新的握手标识 checklinkname :向 cmd/link 引入新的 -checklinkname=1 标志,该标志要求 Go 标准库中的内部符号采用新的握手的机制。
  2. 查找和标记正在使用的开源库 :调查所有现有的开源 Go 软件包,以查找使用正在背后使用 //go:linkname 的标准库符号。向标准库添加必要的 //go:linkname 注释以保持这些注释正常工作,并记录每个注释存在的原因。
  3. 新版本将 checklinkname 设置为默认 :将 -checklinkname=1 设为 Go 1.23 的默认设置。如果这导致任何中断,用户可以使用 -ldflags=-checklinkname=0 来解决问题,我们希望他们能提交报告,让我们知道我们遗漏了什么。

可以达到的目的

虽然 rsc 做了各种措施,依然无法达到 rsc 心目中的理想、美好 Go 世界。但是至少可以达到以下两个核心目的:

  • 不会破坏任何原有东西,保持对现有已经引用的 linkname 的支持。(煎鱼:这个后面狠狠打脸了)
  • 可以将阻止新的损害累积,也就是不会再引入对 runtime 内部的新 linkname 引用。未来也不会有任何由外部新的引用。

戏剧一幕

rsc 直接冷不丁搞大招。他直接把国内外好几个知名库给直接钉上了 Go 源码库的耻辱柱上了。

如下图所示:

详情可以具体查看《国内外多个库被 rsc 钉上 Go 耻辱柱。。。》,我就不再赘述了。

争议

这方面争议是不小的,摘抄其中一句比较有冲击的。

社区有位网友 @szmcdull 直接怒评:"我们是黑客,我们不需要一些对儿童安全的玩具。"

总结

这次 rsc 可能是在回顾 go issues 或处理相关 //go:linkname 的兼容性逻辑处理时,发现了这个一直会给内外部带来破坏性更新的地方。

这显然和 Go1 的兼容性保障相违背的,虽然这是直接拿了合法钥匙去 Go 家的后院把东西给接上了。

为此这次也输出了 -checklinkname=1 的握手模式把这个后院给堵住了。rsc 的执行力确实是很猛的!

  • 本文作者:煎鱼
  • 公众号:脑子进煎鱼了
  • 联系方式(微信号):cJY0728(加我拉你进技术交流群)

文章持续更新,可以微信搜【脑子进煎鱼了】阅读,本文 GitHub github.com/eddycjy/blo... 已收录,学习 Go 语言可以看 Go 学习地图和路线,欢迎 Star 催更。

推荐阅读

相关推荐
newerp2 天前
Go net/http 标准库基础
后端·程序员·go
2651940511264802 天前
01-整体架构与高可用
go
程序员爱钓鱼2 天前
Go if 判断详解
前端·后端·go
名字还没想好☜2 天前
Go 的 unsafe.Pointer 实战:零拷贝 []byte↔string 转换与三条铁律
开发语言·后端·golang·go·unsafe
阿里云云原生2 天前
阿里云联合 Datadog,补齐 Go 可观测性最后短板
云原生·go
可观测性用观测云2 天前
零码改造!Go 语言应用上报观测云完整最佳实践
go
斐波那契数列2 天前
参考react 实现一个golang gui
go
程序员爱钓鱼3 天前
Go 运算符详解
后端·面试·go
angryshan3 天前
goLang配置断点流程
go·bug
名字还没想好☜3 天前
Go 的 sync.Cond 实战:用条件变量做等待/通知,比忙轮询省 CPU
开发语言·数据库·后端·golang·go