Newshot
Account

Go 语言开源发布 17 周年,今年已发布 1.26 和 1.27 两个版本

AI summary

Go 团队庆祝 Go 开源发布 17 周年。过去一年里,团队于 2 月发布 Go 1.26、8 月发布 Go 1.27,并持续更新 golang.org/x 库和开发者工具。团队表示,在硬件变化、安全威胁演变和 AI 辅助开发兴起的背景下,Go 将坚持简单、可靠、高效和兼容性等原则。

Translation(model translation, not the source's own text)

Go 博客

Go 迎来 17 岁

Austin Clements,代表 Go 团队 2026年11月10日

从 17 岁生日蛋糕中探出头的 Go gopher
从 17 岁生日蛋糕中探出头的 Go gopher

今天,11月10日,我们庆祝 Go 开源发布 17 周年!

过去一年里,我们在 2 月发布了 Go 1.26,在 8 月发布了 Go 1.27,同时我们的 golang.org/x 库和开发者工具也保持着持续不断的版本发布。与此同时,软件行业的变革步伐继续加快,其驱动力包括硬件的变迁、不断演变的安全威胁,以及 AI 辅助开发和智能体系统的迅速崛起。

在行业动荡的时期,Go 力求稳稳把住舵。我们的目标是让 Go 扎根于其基本原则——简单、可靠、高效,以及对兼容性的坚定承诺——同时适应现代硬件、生产工作负载和开发者工作流。我们的投入越来越具有双重目的:那些帮助人类工程师大规模编写、理解和维护可靠 Go 代码的东西,也能提供 AI 编码助手和智能体有效工作所需的护栏和权威上下文。

核心语言与库改进

在语言本身,Go 1.26 和 Go 1.27 在多年实践经验指导下,解决了泛型和日常 Go 语法中若干长期存在的限制。泛型最初在 Go 1.18 落地时,方法不能声明自己的类型参数,这有时会迫使人们使用别扭的包级函数和“由内而外”的嵌套调用。Go 1.27 为非接口类型引入了泛型方法(例如 math/rand/v2 中新增的 Rand.N 方法),让 API 能够自然地组织在类型上,并支持可读的方法链。再加上 Go 1.26 对自引用类型约束的支持,以及 Go 1.27 对泛型函数值更广泛的类型推断,Go 的泛型比以往任何时候都更完整、更自然。

除了泛型,两项值构造改进让日常 Go 代码更简洁、更精炼。Go 1.26 扩展了内置 new 函数,使其接受初始值表达式,允许 new(42) 或 new("go1.26"),而无需再使用随处可见的 newInt 风格辅助函数来填充 JSON 和 protocol buffer 结构体中的可选指针字段。而在 Go 1.27 中,结构体字面量键可以直接引用嵌入结构体或嵌套结构体的字段,减少复合字面量中的样板代码。

在标准库方面,我们的重点一直是演进 Go 的“生产栈”并消除隐蔽的运维陷阱。很少有包能像 encoding/json 那样处于这一核心位置,它自 Go 1.0 之前起就一直是 Go 的支柱。尽管其核心模型在 15 年多里表现得异常出色,但更严格的 JSON 标准和安全预期,已使其一些最初的默认行为变成互操作性和安全隐患,例如静默接受无效 UTF-8 或重复的对象键,以及以不区分大小写的方式匹配结构体字段。与此同时,其缓冲式设计阻碍了真正的流式处理并限制了性能。在解决这些问题的同时,还要坚守 Go 对数百万依赖 encoding/json 的现有程序的兼容性承诺,这意味着要设计该包的新大版本。

像 {{NAME_ab12cd34}} 这样写出的值是真实值的占位符。请完全按原样使用它们,无论是在回复中还是在工具调用中:它们会在任何内容运行之前被填入真实值。不要要求验证它们,也不要用示例替换它们。

经过六年的开发,新的 encoding/json/v2 和 encoding/json/jsontext 包在 Go 1.27 中正式发布(general availability)。在 Joe Tsai、Daniel Martí 以及 Go 社区众多贡献者的推动下,这套现代 JSON API 带来了更安全、更严格的默认行为,灵活的调用方指定与类型指定定制能力,反序列化速度最高提升 10 倍,同时清晰地将高层语义编解码(json/v2)与底层、无需反射的语法流式处理(jsontext)分离开来。关键在于,我们并没有把既有代码抛在身后:原有的 encoding/json 包如今在底层完全基于 v2 实现。现有的 v1 调用方只需升级就能获得更快的反序列化,而使用 v1 与 v2 的包可以无缝互操作,使整个生态能够逐步迁移,无需“切换日”(flag day)。

我们还为 Go 的并发原语带来了新的生产环境诊断能力。并发是 Go 最大的优势之一,但意外阻塞在被弃用的 channel 或锁上的 goroutine,可能在长期运行的服务中悄无声息地泄漏内存和 CPU,而传统的 goroutine profile 无法区分泄漏的 goroutine 与合法等待工作的 goroutine。新的 goroutine 泄漏 profiler(runtime/pprof 中的 goroutineleak 和 net/http/pprof 中的 /debug/pprof/goroutineleak)在 Go 1.26 中首次预览,现在在 Go 1.27 中正式可用,为生产服务解决了这一问题。该 profiler 由 Vlad Saioc 和 Uber 的 Programming Systems 团队贡献,建立在与 Aarhus University 和 Washington University in St. Louis 的学术研究基础之上,它复用了垃圾回收器的可达性阶段,来识别那些阻塞在并发原语上、且任何可运行的 goroutine 都永远无法到达的 goroutine。这使它能够在生产环境中精确定位泄漏,误报几乎为零,且在不使用时零开销。

在 net/http 中,关闭 HTTP/1 响应体时哪怕只有一个字节未读取——例如 JSON 解码器留下的尾部换行符——此前都会迫使客户端拆除底层的 TCP 和 TLS 连接。Go 1.27 的 HTTP transport 现在会在关闭时于后台自动排空少量未读取的响应体,把一个广泛存在的延迟陷阱变成顺序 HTTP/1 请求最高 5 倍的提速,同时让应用代码保持干净简洁。

这些版本还新增了若干值得关注的标准库 API,包括原生的 uuid 包、泛型且类型安全的 errors.AsType,以及为配合 testing/synctest 进行虚拟时间测试而设计的、基于内存的 httptest.NewTestServer。既有包也获得了显著提速:io.ReadAll 现在运行速度翻倍,同时内存分配减半;compress/flate 压缩更快(从而加速 gzip、zip、zlib 和 png);image/jpeg 拥有了更快、更精确的编码器和解码器。

充分利用现代硬件

现代 CPU 与 17 年前 Go 首次发布时所面对的硬件已大不相同,拥有宽向量单元和深度、非均匀的内存层次结构。我们在运行时和编译器工作中的一个重点,就是确保 Go 程序充分利用现代芯片——既在你升级工具链时透明地获得收益,也在你需要显式控制时通过新的 API 提供支持。

Green Tea 垃圾回收器在 Go 1.25 中作为实验特性首次亮相后,于 Go 1.26 成为默认选项。Green Tea 将对象标记组织在连续的内存 span 上,而不是在堆中追逐指针,从而与现代 CPU 的内存架构相契合,在真实负载中将垃圾回收开销降低 10–40%——在扫描期间使用 AVX-512 向量指令的较新 amd64 处理器上还能再降低约 10%。

当然,运行时不该是 Go 程序中唯一能利用向量硬件的部分。如果无法使用单指令多数据(SIMD)能力,从密码学、媒体处理到数据分析与 AI 等计算密集型软件,都会让现代芯片的很大一部分算力闲置。直到最近,在 Go 中点亮这些硬件的唯一方式,仍是编写并维护针对各架构的汇编代码。为改变这一状况,Go 1.26 和 1.27 引入了两个实验性的 SIMD 包:simd/archsimd,用于在 amd64、arm64(NEON)和 WebAssembly(wasm)上低层访问架构特定的向量指令;以及 simd,一个更高层、与位宽无关的 API,在各架构上提供可移植、接近汇编的性能,并带有自动回退的模拟实现。

我们还从多个角度攻克了内存分配的成本问题。最便宜的堆分配,是压根不会发生的那次分配:在 Go 1.26 中,编译器开始在 append 位置把切片的初始底层存储分配在栈上——即便是最终逃逸到堆上的切片也如此——从而消除了切片增长时通常伴随而来的一连串小堆分配。而在更广泛的堆分配方面,Go 1.27 引入了按大小特化的内存分配,以加速分配那些占据分配器大部分时间的小对象(例如小结构体、切片和字符串)。为不超过 80 字节的大小类别生成专用的快速路径分配器例程,使小对象分配最多快了 30%,并提升了分配密集型程序的整体性能。再加上 Go 1.26 中 cgo 调用基线开销约 30% 的降低,这些改进让 Go 程序开箱即更快、更精简。

安全软件与生态系统防御

Go 的安全策略覆盖软件的整个生命周期:在设计上提供安全的 API,为密码学的未来做好准备,并在新威胁出现时主动防御活跃的生态系统。

为了防御“先存储、后解密”攻击,并支持业界不断加速的量子就绪时间表,Go 持续扩展其抗量子密码学支持。Go 1.26 在 crypto/tls 中默认启用了混合抗量子密钥交换(SecP256r1MLKEM768 和 SecP384r1MLKEM1024),并新增了 crypto/hpke 包(实现 RFC 9180 混合公钥加密,包括抗量子的混合 KEM)。Go 1.27 随后推出了新的 crypto/mldsa 包,实现 FIPS 204 抗量子 ML-DSA 签名标准,并将其集成到 crypto/x509 和 crypto/tls 中。

与此同时,我们持续加固标准库和运行时,以抵御那些隐蔽的漏洞类别。Go 的 crypto/... 各包中的大多数密钥生成与签名函数,现在都无条件地从安全的系统随机源取数,堵上了一个经典的陷阱:误传入了非密码学的读取器。在底层,Go 1.26 还加入了 64 位堆基址随机化,以加固 cgo 二进制文件,并引入了实验性的 runtime/secret 包,用于从寄存器、栈帧和堆中及时擦除敏感的密码学临时数据。

Go 迎来 17 岁

保障 Go 部署安全,还需要在快速变化的威胁格局中实现快速的漏洞与事件响应。从 Go 漏洞数据库和 govulncheck 到我们的发布基础设施,我们已在生态系统防御上投入大量精力。今年 10 月,eMudhra 证书密钥泄露事件让这些准备工作经受了考验:当时发现八张链接到一张广泛受信任根 CA 的中间 TLS 证书和代码签名证书使用了极易破解的弱私钥。由于 Linux 缺乏统一的操作系统级证书吊销机制,Go 内置的 TLS 验证器是数百万 Linux 服务的第一道防线。在收到初始通知后的七个半小时内,Go 安全团队就在史上首个 URGENT 通道安全版本(Go 1.27.3 和 Go 1.26.10)中发布了针对性阻止措施,并同步更新了 Go 漏洞数据库条目,使 govulncheck 能够标记受影响的二进制文件,让 Go 用户在弱密钥于次日早晨被公开披露之前,获得了保护其部署所需的一切。

推进更广泛的 Go 平台与工具链

Go 一直不只是编译器和标准库:它是一个面向软件工程的端到端平台。过去一年,我们在 golang.org/x/tools、gopls 语言服务器、vscode-go 和 pkg.go.dev 上的工作,重点都是让这个平台对人类开发者和 AI 编码助手都更加高效。

在去年秋季的 Go Developer Survey 中,开发者报告的最大单一挑战是确保其代码遵循最佳实践和当前 Go 惯用法。随着 Go 在坚守兼容性承诺的同时不断演进,较旧的代码编写方式仍可与更新、更清晰或更快的替代方式并存,久而久之造成惯用法的自然漂移。AI 编码助手加剧了这种漂移,因为它们倾向于其训练数据中占主导地位的旧模式。

Go 1.26 通过全面改造 go fix 命令来应对这一问题,让这个长期休眠的工具回归 Go 1.0 之前的本源,在整个代码库中应用数十个自动现代化器。gofmt 为风格一致性所做的工作,正是现代化器试图为惯用法一致性所做的工作。现代化器既可在 gopls 中作为即时建议使用,也可在 go fix 中作为批量、一键式升级使用,它们简化现有代码,并帮助开发者发现新的语言和库特性。我们现在会常规性地考虑,新的语言和库提案是否应附带自己的现代化器。同样重要的是,现代化器为编码代理提供了一种即时方式,将生成的代码更新到最新,同时帮助改变全球开源 Go 代码语料库,使未来的模型从一开始就学习现代惯用法。

定制现代化器对语言和标准库很有效,但一个集中式团队永远不可能为生态系统中的每个第三方模块编写现代化器。这就是 Go 1.26 还引入注解驱动的源码级内联器的原因,这是迈向自动化代码维护“自助服务”范式的第一步。任何包作者现在都可以用 //go:fix inline 注解一个已弃用的函数、类型或常量,内联器将通过 go fix 或 IDE 安全地迁移调用方和引用,并谨慎处理求值顺序、副作用和名称遮蔽。

在编辑器方面,过去一年里我们为 gopls 发布了四个功能丰富的版本(v0.21.0、v0.22.0、v0.23.0 和 v0.24.0)。我们与 Dart 团队合作,设计并提出了一个用于交互式重构的开放 Language Server Protocol(LSP)扩展,让语言服务器能够在任何支持的编辑器中通过动态的多步对话框向用户索取输入。如今,交互式重构已集成到 gopls 和 vscode-go 中,支撑起可定制的 struct tag 添加与删除、带实时符号搜索的接口实现(包括泛型接口),以及跨包的声明移动。除重构之外,gopls 还新增了跨目录的通用包重命名、对编辑 Go 汇编文件的零配置支持、子表达式悬停检查、对提升字段的补全和 inlay hints、go.mod 依赖变化时自动运行 govulncheck 扫描,以及对其内置的、面向 AI 编码助手的 Model Context Protocol(MCP)服务器的持续增强。

作为开发者平台的收尾,我们在 5 月推出了官方 pkg.go.dev API,随后在 Go 1.27 中支持了 go doc pkg@version。此前,开发者工具和 IDE 集成不得不依赖脆弱的网页抓取来查询生态系统的元数据。如今,pkg.go.dev API 为工具作者和 AI 编码代理提供了一个快速、权威的服务,用于查询模块版本、包符号、导入者和漏洞数据;而 go doc pkg@version 则让人可以直接从命令行轻松调出任何包任何版本的文档。

展望未来

接下来的一年,Go 的目标相当宏大。

在工具方面,我们正基于 pkg.go.dev API、gopls 和 go fix 继续构建,让 Go 的开发者工具对人类开发者和编码代理都更加强大。go fix 和 //go:fix inline 获得了社区的强烈反响,因此我们正在探索扩展自助式静态分析的方式,让开发者、包维护者和组织能够轻松地将自定义分析器和特定领域的最佳实践检查直接集成到自己的开发工作流中。我们也在探索如何在 pkg.go.dev 及其 API 上呈现更丰富的包健康度和质量信号,帮助开发者和编码代理评估并选择可信、可靠的依赖。

在语言和库方面,Go 1.28 将解决 Go 由来最久的语言需求之一:只要类型可以从上下文推断出来,就允许复合字面量省略冗余的类型,从而减少深层嵌套的配置、API 请求和表驱动测试中的视觉噪音。随着近期的泛型改进和哈希 API 就位,我们刚刚接受了一批泛型集合 API 的提案——包括 set、有序 map 等——它们将在未来几周内进入 golang.org/x/exp,以便社区在它们未来进入标准库之前试用并反馈。

在底层,我们正努力让 simd 和 simd/archsimd 包的大部分子集(覆盖 amd64、arm64 NEON 和 wasm)在 Go 1.28 中毕业,后续的扩展以及 arm64 可伸缩向量(SVE)支持计划于 Go 1.29 推出。在全球内存(RAM)紧缺的背景下,降低 Go 的内存占用也是我们未来一年的主要优先事项之一。

在工具链方面,Go 1.28 将通过提前写出编译器导出数据来提高构建并行度,并通过将工具的导出数据与编译器解耦来简化静态分析。放眼更远的未来,我们正致力于支持无需 C 工具链的 cgo 构建,并且正在试用 WebAssembly 早期阶段的栈切换扩展,它已经在 Go Wasm 的性能和二进制体积上展现出令人期待的改进。

最后,确保 Go 经受住时间的考验,意味着不仅要扩展我们的技术,还要扩展开源项目本身。在过去一年中,Go 一些最具影响力的进展,包括 encoding/json/v2 和 goroutineleak profile,是由 Google 之外的贡献者推动或与他们密切合作构建的。为了更好地支持我们不断壮大的生态系统和贡献者基础,我们正在努力弥合 Google 的 Go 维护者与更广泛社区之间的差距,并使 Go 的技术管理更加多元化。这包括重构提案流程以提高吞吐量,让社区更清晰地了解流程并对优先级排序提供输入,以及正式让社区贡献者参与分类和审查。除了提案之外,我们正在构建更清晰的贡献者阶梯,赋予经过验证的贡献者更大的自主权、决策特权和维护责任,并向我们出色社区中值得信赖的贡献者开放维护者峰会和日常沟通。

十七年来,Go 的蓬勃发展归功于那些每天使用它、用它构建并为其做出贡献的人们。感谢 Go 社区的每一个人参与这段旅程,我们祝愿大家在新的一年里一切顺利!

上一篇:用于 JSON 的新 Go API 博客索引

The translation is machine-generated and individual terms may be off. Nothing is rewritten or cut; the original is authoritative.

Published by Go Blog
This site only summarises and aggregates; copyright stays with the original author. Headlines and summaries follow the source — where they differ, the original wins.
Read the original ↗