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

推荐阅读

相关推荐
蒙娜丽宁2 天前
Go语言错误处理详解
ios·golang·go·xcode·go1.19
qq_172805593 天前
GO Govaluate
开发语言·后端·golang·go
littleschemer3 天前
Go缓存系统
缓存·go·cache·bigcache
程序者王大川4 天前
【GO开发】MacOS上搭建GO的基础环境-Hello World
开发语言·后端·macos·golang·go
Grassto4 天前
Gitlab 中几种不同的认证机制(Access Tokens,SSH Keys,Deploy Tokens,Deploy Keys)
go·ssh·gitlab·ci
高兴的才哥5 天前
kubevpn 教程
kubernetes·go·开发工具·telepresence·bridge to k8s
少林码僧6 天前
sqlx1.3.4版本的问题
go
蒙娜丽宁6 天前
Go语言结构体和元组全面解析
开发语言·后端·golang·go
蒙娜丽宁6 天前
深入解析Go语言的类型方法、接口与反射
java·开发语言·golang·go
三里清风_6 天前
Docker概述
运维·docker·容器·go