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 催更。

推荐阅读

相关推荐
一点一木13 小时前
WebAssembly:Go 如何优化前端性能
前端·go·webassembly
27669582922 天前
阿里1688 阿里滑块 231滑块 x5sec分析
java·python·go·验证码·1688·阿里滑块·231滑块
Moment4 天前
在 NodeJs 中如何通过子进程与 Golang 进行 IPC 通信 🙄🙄🙄
前端·后端·go
唐僧洗头爱飘柔95274 天前
(Go基础)变量与常量?字面量与变量的较量!
开发语言·后端·golang·go·go语言初上手
黑心萝卜三条杠4 天前
【Go语言】深入理解Go语言:并发、内存管理和垃圾回收
google·程序员·go
不喝水的鱼儿4 天前
【LuatOS】基于WebSocket的同步请求框架
网络·websocket·网络协议·go·luatos·lua5.4
微刻时光5 天前
程序员开发速查表
java·开发语言·python·docker·go·php·编程语言
lidenger5 天前
服务认证-来者何人
后端·go
幼儿园老大*6 天前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
童先生6 天前
Go 项目中实现类似 Java Shiro 的权限控制中间件?
开发语言·go