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

推荐阅读

相关推荐
源代码•宸1 天前
Leetcode—1929. 数组串联&&Q1. 数组串联【简单】
经验分享·后端·算法·leetcode·go
nil1 天前
记录protoc生成代码将optional改成omitepty问题
后端·go·protobuf
Way2top2 天前
Go语言动手写Web框架 - Gee第五天 中间件
后端·go
Way2top2 天前
Go语言动手写Web框架 - Gee第四天 分组控制
后端·go
Grassto2 天前
从 `go build` 开始:Go 第三方包加载流程源码导读
golang·go·go module
源代码•宸3 天前
Golang基础语法(go语言结构体、go语言数组与切片、go语言条件句、go语言循环)
开发语言·经验分享·后端·算法·golang·go
華勳全栈3 天前
两天开发完成智能体平台
java·spring·go
stark张宇4 天前
Go语言核心三剑客:数组、切片与结构体使用指南
后端·go
Aevget4 天前
智能高效Go开发工具GoLand v2025.3全新上线——新增资源泄漏分析
开发语言·ide·后端·golang·go
wwz165 天前
Dagor —— 一个高性能 DAG 算子执行框架,开箱即用!
go