Go 团队隆重宣布 Go 1.23 版本正式发布!距离上个版本 Go 1.22 发布已经过去了六个月,这次更新带来了许多令人兴奋的新功能和改进。本文将深入探讨 Go 1.23 的主要变化,包括语言变化、工具链更新、标准库增强以及对不同平台的支持。

语言变化:迭代函数和泛型别名

Go 1.23 在语言层面上的最大亮点是将“range-over-func”实验性功能正式纳入语言规范。现在,for-range 循环中的 range 子句可以接受以下类型的迭代函数作为范围表达式:

func(func() bool)
func(func(K) bool)
func(func(K, V) bool)

迭代函数的调用将为 for-range 循环生成迭代值。更多详细信息请参考 iter 包文档和语言规范。

此外,Go 1.23 还引入了对泛型类型别名的预览支持。通过设置环境变量 GOEXPERIMENT=aliastypeparams,您可以在包内启用此功能。但需要注意的是,跨包边界使用泛型别名类型尚不支持。

Telemetry:帮助 Go 团队更好地了解 Go 的使用情况

从 Go 1.23 开始,Go 工具链可以收集使用情况和错误统计信息,以帮助 Go 团队了解 Go 工具链的使用方式及其运行状况。我们将这些统计信息称为 Go Telemetry。

Go Telemetry 是一个可选系统,由 go telemetry 命令控制。默认情况下,工具链程序将统计信息收集到计数器文件中,这些文件可以在本地进行检查,但不会被其他方式使用(go telemetry local)。

为了帮助我们保持 Go 良好运行并了解 Go 的使用情况,请考虑通过运行 go telemetry on 选择加入 Go Telemetry。在这种模式下,匿名计数器报告将每周上传到 telemetry.go.dev,并在那里汇总成图表,供任何想要分析数据的 Go 贡献者或用户下载。有关 Go Telemetry 系统的更多详细信息,请参阅“Go Telemetry”。

Go 命令:改进模块管理和环境变量设置

  • 设置 GOROOT_FINAL 环境变量不再有任何效果。建议将 go 命令安装到 $GOROOT/bin/go 以外的路径时,应该安装一个符号链接,而不是重新定位或复制 go 二进制文件。
  • 新增 go env -changed 标志,该标志将只打印那些有效值与其默认值不同的设置。
  • 新增 go mod tidy -diff 标志,该标志将不会修改文件,而是以统一的差异格式打印必要的更改。如果需要更新,它将以非零代码退出。
  • go list -m -json 命令现在包含新的 SumGoModSum 字段。这类似于 go mod download -json 命令的现有行为。
  • go.modgo.work 中新增 godebug 指令,用于声明要应用于正在使用的模块或工作区的 GODEBUG 设置。

其他重要更新

  • Vet: go vet 子命令现在包含 stdversion 分析器,它会标记对那些对于引用文件中生效的 Go 版本来说太新的符号的引用。
  • Cgo: cmd/cgo 支持新的 -ldflags 标志,用于将标志传递给 C 链接器。go 命令会自动使用它,以避免在 CGO_LDFLAGS 非常大的情况下出现“参数列表过长”的错误。
  • Trace: trace 工具现在可以更好地容忍部分损坏的跟踪,方法是尝试恢复它可以恢复的跟踪数据。当查看在程序崩溃期间收集的跟踪时,此功能特别有用,因为在大多数情况下,现在可以恢复导致崩溃的跟踪数据。
  • Runtime: 在未处理的 panic 或其他致命错误之后,运行时打印的回溯现在将错误消息的第二行和后续行(例如,panic 的参数)缩进一个制表符,以便可以将其与第一个 goroutine 的堆栈跟踪明确区分开来。
  • Compiler: 使用配置文件引导优化 (PGO) 进行构建时的构建时间开销已显着减少。以前,大型构建可能会看到启用 PGO 后构建时间增加 100% 以上。在 Go 1.23 中,开销应该在个位数百分比。
  • Linker: 链接器现在禁止使用 //go:linkname 指令来引用标准库(包括运行时)中未在其定义上标记 //go:linkname 的内部符号。类似地,链接器也禁止从汇编代码中引用此类符号。为了向后兼容,仍然支持在大型开源代码库中发现的 //go:linkname 的现有用法。任何对标准库内部符号的新引用都将被禁止。
  • 标准库: Go 1.23 对标准库进行了多项改进,包括:
    • time.Timertime.Ticker 的实现进行了两项重大更改:未引用的计时器和周期性计时器现在可以立即进行垃圾回收,即使它们的 Stop 方法尚未被调用;与计时器或周期性计时器关联的计时器通道现在是无缓冲的,容量为 0。
    • 新增 unique 包,提供用于规范化值(如“interning”或“hash-consing”)的工具。
    • 新增 iter 包,提供用于处理用户定义迭代器的基本定义。
    • 新增 structs 包,提供用于修改包含结构类型属性(如内存布局)的结构字段的类型。
    • 对其他标准库包进行了多项小的更改和改进。

平台支持

  • Darwin: Go 1.23 要求 macOS 11 Big Sur 或更高版本;已停止支持以前的版本。
  • Linux: Go 1.23 是最后一个需要 Linux 内核版本 2.6.32 或更高版本的版本。Go 1.24 将需要 Linux 内核版本 3.17 或更高版本,但运行 3.10 或更高版本且已修补内核以支持 getrandom 系统调用的系统除外。
  • OpenBSD: Go 1.23 增加了对 64 位 RISC-V (GOOS=openbsdGOARCH=riscv64) 上 OpenBSD 的实验性支持。
  • ARM64: Go 1.23 引入了一个新的 GOARM64 环境变量,用于在编译时指定 ARM64 架构的最低目标版本。允许的值为 v8.{0-9}v9.{0-5}
  • RISC-V: Go 1.23 引入了一个新的 GORISCV64 环境变量,用于选择要为其编译的 RISC-V 用户模式应用程序配置文件。允许的值为 rva20u64rva22u64
  • Wasm: GOROOT/misc/wasm 中的 go_wasip1_wasm_exec 脚本已放弃对 wasmtime < 14.0.0 版本的支持。

总结

Go 1.23 版本带来了许多令人兴奋的新功能和改进,包括语言变化、工具链更新、标准库增强以及对不同平台的支持。这些更新将使 Go 语言更加强大、高效和易于使用。我们鼓励所有 Go 用户升级到最新版本,以体验这些新功能和改进。