17611538698
info@21cto.com

Go 1.26 悄然修复了哪些真正令人恼火的问题

编程语言 0 15 1小时前
图片

21CTO导读:大多数版本说明文章读起来都像变更日志,而这份版本说明读起来却像是一连串的有趣的道歉声明。以下列出了变更内容、变更原因以及可以忽略的内容。

我阅读 Go 1.26 发行说明的方式与阅读大多数开源软件发行说明的方式相同:快速浏览主要功能,忽略其余部分,然后再回到我的源代码中。

然后,我又再次读了一遍。

我第二次注意到,1.26 版本几乎没有什么引人注目的改动。没有会在 Hacker News 上爆红的新语言特性,也没有“Go 获得异步功能”这样的重大事件。相反,它悄然修复了多年来一直困扰 Go 开发者的问题,并带来了一项真正重要的运行时变更,几乎所有生产服务都将从中受益。

让我带你了解一下实际发生了哪些变化,你应该关注哪些方面,以及你可以忽略哪些方面。

Green Tea现在是默认的垃圾回收器


如果这篇文章你只能读一部分,那就请读这一部分。

Go 1.25 将 GreenTea (绿茶)垃圾回收器作为可选实验方案推出。Go 1.26 则将其设为默认方案。Go 团队报告称道,在实际程序中, GC 开销降低了 10% 到 40%,如果运行在 Intel Ice Lake 或 AMD Zen 4 或更新的处理器上,还能在此基础上再降低约 10%(因为新的回收器使用向量指令来扫描小对象)。

我需要谨慎对待这个数字,因为“10%–40%”这个范围本身意义不大,需要结合上下文才能理解。这里需要说明的是:这是垃圾回收 (GC) 时间的减少,而不是总运行时间的减少。如果你的服务 20% 的 CPU 都花在了 GC 上,那么你只需要将 CPU 使用率降低到 12% 到 18% 之间。这不需要重写代码,简直是轻而易举。

GOEXPERIMENT=greenteagc

你无需进行任何操作即可获得此功能。升级到 1.26 版本后,您的服务会自动获得此功能。如果你已经在 1.25 版本中运行此功能,则可以安全移除该标志。

实际的语言更改:使用新表达式new()


这个虽然是件小事,但也是多年来我一直渴望的改变。

在 Go 1.26 中,内置new函数接受一个表达式作为其操作数:

func personJSON(name string, born time.Time)([]byte,error) {  return json.Marshal(    Person{      Name: name,      Age:      new(yearsSince(born)),// ← 这里是new    })}
在 1.26 版本之前,你需要分两步编写这段代码:
age := yearsSince(born)  return     json.Marshal(Person{                  Name: name,                  Age: &age,    })
虽然应用场景比较窄,但确实存在实用点:任何指向可选值的指针字段(JSON、protobuf、gRPC),现在都可以直接内联填充。这种变化在基准测试中可能不明显,但在你做过的每一次代码审查中都会体现出来。

你可能永远不会直接使用泛型更改。泛型类型不能在其类型参数列表中引用自身的限制已被取消:

type Adder[A Adder[A]]interface {  Add(AA}

这是库作者非常喜欢的特性,而应用程序开发者则无需再编写任何代码。如果你正在构建数学库或集合框架,这将带来更简洁的抽象。如果你正在构建 Web 服务,则可以跳过这一部分。

能够为你节省数小时的工具变革:go fix重生了


这是我最期待的改变,但却是没人谈论的改变。

go fix它已完全重写。现在,它是 Go 语言现代化工具的家园——数十个自动化修复工具,可将你的代码更新为使用现代的惯用法和 API。它使用与 Go 相同的分析框架go vet,这意味着你已经信任的诊断工具现在可以建议并应用修复。

最强大的功能是源代码级内联。如果您维护一个库,并希望用户迁移到新的 API,您可以编写一个//go:fix inline指令,系统go fix会自动重写他们的代码。

实际上,这意味着:

  • 将 Go 项目升级到 1.26现在go fix ./...不再需要使用新的惯用法。
  • 从已弃用的 API 迁移不再是手动执行 grep 和替换操作。
  • 库作者可以通过自动迁移路径发布重大变更。


如果你曾经维护过庞大的 Go 代码库,并且害怕收到“升级 Go 版本”的 PR,那么这篇文章就是为你准备的。

值得了解的较小运行时变化


Go 1.26 版本中还包含了其他三项运行时变更:


更快的 cgo 调用。如果你有一个 Go 服务需要调用 C 库(例如数据库驱动程序、图像处理程序或任何封装了 C API 的库),那么 cgo 的开销现在大大降低了。Go 团队尚未公布具体数值,但此次改进旨在降低每次调用的开销,尤其是在高负载路径中。


堆基地址随机化。这是一项安全加固措施。堆基地址现在已随机化,这使得某些内存损坏攻击更难得逞。您在代码中不会注意到这一点,但您的安全团队会在他们的威胁模型中发现它。


实验性 goroutine 泄漏分析。一种新的pprof分析类型,用于检测 goroutine 泄漏。此功能尚处于实验阶段,因此请勿将其用于生产环境调试,但值得在测试套件中尝试。


标准库新增内容


1.26 发布三个新库。包括如下:


  • crypto/hpke— 混合公钥加密。如果你曾经需要在不事先进行密钥交换的情况下使用公钥加密数据,那么这就是标准做法。它现在已集成到标准库中,不再是第三方依赖项。

  • simd/archsimd(实验性)— SIMD 原语。如果您一直想用 Go 编写向量化代码,又不想直接使用汇编语言,那么这就是基础。它目前处于实验阶段,因此 API 会不断变化,但方向很明确:Go 正在认真提升 CPU 级性能。

  • runtime/secret(实验性)——一个用于管理密钥的软件包,无需将其暴露在堆栈跟踪、崩溃消息或日志中。这种功能早就应该出现了。它目前仍处于实验阶段,但如果按原样发布,将是一项真正的安全改进。


工具清理


你应该了解的两项变化:


  • cmd/docgo tool doc已被删除。请改用go doc等其他方法。相同的标志,相同的行为。如果你有调用该方法的脚本go tool doc,请立即更新它们。

  • pprof网页界面默认显示火焰图。如果你更喜欢旧版图表视图,它仍然位于“视图”→“图表”下,或者在/ui/graph

可以忽略什么


并非版本发布中的每一项变更对每位开发者都至关重要。以下变更可以忽略:


  • 自引用泛型类型更改——除非你在编写数学库,否则你不会碰它。
  • 新的实验性软件包simd/archsimdruntime/secret)——它们是实验性的,API 将会改变,你现在不应该用它们构建生产系统。
  • 平台特定的更改(Darwin、FreeBSD、Windows、PowerPC、RISC-V、S390X、WebAssembly)——只有在部署到这些平台时才重要。

本周你要做什么


  1. 将非生产环境服务升级到 1.26 版本。看看 Green Tea 是否能带来版本说明中承诺的 GC 改进。
  2. go fix ./...先在一个小项目上运行一下。看看现代化工具会给出什么建议。你会惊讶地发现,你的代码中有多少地方还在使用过时的写法。
  3. new(expr)下次编写 JSON 序列化函数时可以尝试一下。这只是一个小小的改动,但累积起来会效果显著。

结语:真正的要点


Go 1.26 版本不会引发任何会议型的讨论,但它能让你现有的代码运行得更快、升级更轻松、代码库更简洁,而你无需做任何事情。


单凭Green GC就值得升级,go fix重写也值得升级,new(expr)改动也值得升级。随便选一项,升级就值回票价。


看起来,那些看似平平淡淡的发行版本才是最重要的。

参考资料:


  • Go 1.26 版本发布说明: https://go.dev/doc/go1.26
  • GreenGC提案: https://github.com/golang/go/issues/73581
  • go fix文档: https://go.dev/doc/go1.26#go-fix
  • new(expr)语言规范
  • 自指泛型提案:
    https://go.dev/ref/spec#Allocation
  • HPKE RFC 9180:
    https://datatracker.ietf.org/doc/html/rfc9180Goroutine
  • 泄漏分析文档:  https://go.dev/doc/go1.26#runtime

    评论

    我要赞赏作者

    请扫描二维码,使用微信支付哦。

    分享到微信