Go 1.23 发布说明
Go 1.23 简介
Go 1.23 是 Go 语言的最新发布版本,距离 Go 1.22 发布已经过去了六个月。此版本带来了多项语言变更、工具改进以及标准库的更新。
语言变更
范围迭代器
Go 1.23 将 Go 1.22 中的 range-over-func 实验性功能正式纳入语言规范。在 for-range 循环中,range 子句现在接受以下类型的迭代器函数作为范围表达式:
func(func() bool) func(func(K) bool) func(func(K, V) bool)
这些迭代器函数的调用将产生迭代值。
泛型类型别名预览支持
Go 1.23 提供了对泛型类型别名的预览支持。通过在构建工具链时设置 GOEXPERIMENT=aliastypeparams,可以在包内启用此功能。跨包边界使用泛型别名类型尚不支持。
工具
Telemetry
从 Go 1.23 开始,Go 工具链可以收集使用情况和中断统计信息,以帮助 Go 团队了解 Go 的使用情况。Telemetry 是一个可选系统,通过 go telemetry 命令控制。默认情况下,工具链程序将统计信息收集到本地计数器文件中,但不会上传。若要选择加入 Telemetry,请运行 go telemetry on。在该模式下,匿名计数器报告将每周上传到 telemetry.go.dev,并聚合成图表供 Go 贡献者或用户分析。
Go 命令
- • 设置
GOROOT_FINAL环境变量不再生效(#62047)。 - •
go env -changed标志仅打印那些有效值与默认值不同的设置。 - •
go mod tidy -diff标志不修改文件,而是将必要的更改以统一差异格式打印出来。 - •
go list -m -json命令现在包括新的Sum和GoModSum字段。 - • 新的
godebug指令。
Vet
- • stdversion analyzer:
go vet子命令现在包括stdversion analyzer,该分析器会标记对当前生效 Go 版本中太新的符号的引用。有效版本由文件所在模块的go.mod文件中的go指令以及文件中的任何//go:build约束决定。
Cgo
- • -ldflags 标志:
cmd/cgo支持新的-ldflags标志,用于向 C 链接器传递标志。go命令会自动使用此标志,避免CGO_LDFLAGS非常大时导致的“参数列表过长”错误。
Trace
- • 更健壮的跟踪数据恢复: 跟踪工具现在更好地容忍部分损坏的跟踪数据,尝试恢复可恢复的数据。这在查看程序崩溃期间收集的跟踪时特别有用,因为大多数情况下现在可以恢复崩溃之前的跟踪数据。
Runtime
- • 错误消息缩进: 运行时在打印未处理的 panic 或其他致命错误后,现在会将错误消息的第二行及后续行缩进一个制表符,以便与第一个 goroutine 的堆栈跟踪明确区分。
Compiler
- • PGO 构建时间开销减少: 使用 Profile Guided Optimization (PGO) 构建时的开销已显著降低。在 Go 1.23 中,开销应保持在个位数百分比。
- • 局部变量重叠优化: Go 1.23 编译器现在可以重叠在函数不相交区域中访问的局部变量堆栈帧槽位,从而减少 Go 应用程序的堆栈使用。
- • 热点块对齐: 对于 386 和 amd64,编译器将使用 PGO 信息来对齐循环中的某些热点块,这将以额外的 0.1% 文本和二进制大小为代价,提高 1-1.5% 的性能。
Linker
- • 内部符号引用限制: 链接器现在不允许使用
//go:linkname指令来引用标准库(包括运行时)中未在其定义上标记为//go:linkname的内部符号。同样,链接器也不允许从汇编代码中引用此类符号。 - • -bindnow 标志: 构建动态链接的 ELF 二进制文件(包括 PIE 二进制文件)时,新的
-bindnow标志启用即时函数绑定。
标准库
Timer changes
- • 垃圾收集改进: 不再被程序引用的 Timer 和 Ticker 会立即成为垃圾收集的目标,即使它们的 Stop 方法未被调用。
- • 无缓冲通道: Timer 或 Ticker 关联的通道现在是无缓冲的,容量为 0。
New unique package
- • 值规范化: 提供了用于规范化值(如“interning”或“hash-consing”)的设施。
Iterators
- • iter 包: 提供了用户定义迭代器的基本定义。
- • slices 和 maps 包: 添加了多个与迭代器一起工作的函数。
New structs package
- • HostLayout 类型: 指示具有该类型字段的结构具有符合主机平台期望的布局。
Minor changes to the library
archive/tar
- • 如果
FileInfoHeader的参数实现了新的FileInfoNames接口,则该接口的方法将用于设置文件头的Uname/Gname。这允许应用程序覆盖系统依赖的Uname/Gname查找。
crypto/tls
- • TLS 客户端现在支持 Encrypted Client Hello 草案规范。可以通过设置
Config.EncryptedClientHelloConfigList字段为编码的ECHConfigList来启用此功能。 - •
QUICConn类型现在包括新的事件报告会话恢复的状态,并提供了一种方式为 QUIC 层向会话票据和会话缓存条目添加数据。 - • 从默认列表中移除了 3DES 密码套件(当
Config.CipherSuites为 nil 时)。可以通过将tls3des=1添加到GODEBUG环境变量来恢复默认设置。 - • 实验性的后量子密钥交换机制
X25519Kyber768Draft00在Config.CurvePreferences为 nil 时默认启用。可以通过将tlskyber=0添加到GODEBUG环境变量来恢复默认设置。 - • Go 1.23 更改了
X509KeyPair和LoadX509KeyPair的行为,以填充返回的Certificate.Leaf字段。添加了新的x509keypairleafGODEBUG设置来控制此行为。
crypto/x509
- •
CreateCertificateRequest现在正确支持 RSA-PSS 签名算法。 - •
CreateCertificateRequest和CreateRevocationList现在使用签名者的公钥验证生成的签名。如果签名无效,将返回错误。 - •
x509sha1GODEBUG设置将在下一个 Go 主要版本(Go 1.24)中被移除,届时crypto/x509将不再支持验证使用 SHA-1 签名算法的证书上的签名。 - • 添加了新的
ParseOID函数来解析点编码的 ASN.1 对象标识符字符串。
database/sql
- •
driver.Valuer实现返回的错误现在被包装,以改进在DB.Query、DB.Exec和DB.QueryRow等操作期间的错误处理。
debug/elf
- • 定义了
PT_OPENBSD_NOBTCFI,用于在 OpenBSD 二进制文件上禁用分支跟踪控制流完整性(BTCFI)执行。 - • 定义了符号类型常量
STT_RELC、STT_SRELC和STT_GNU_IFUNC。
encoding/binary
- • 添加了新的
Encode和Decode函数,它们是Read和Write的字节切片等效项。Append允许将多个数据编组到同一个字节切片中。
go/ast
- • 新的
Preorder函数返回一个方便的迭代器,遍历语法树的所有节点。
go/types
- •
Func类型现在有一个Func.Signature方法,该方法返回函数的类型,它总是一个Signature。 - •
Alias类型现在有一个Rhs方法,返回其声明右侧的类型。 - • 添加了
Alias.Origin、Alias.SetTypeParams、Alias.TypeParams和Alias.TypeArgs方法,这些方法对于泛型别名类型是必需的。 - • 默认情况下,
go/types现在为类型别名生成Alias类型节点。此行为可以通过GODEBUG gotypesalias标志控制,其在 Go 1.22 中的默认值为 0,在 Go 1.23 中更改为 1。
math/rand/v2
- • 添加了
Uint函数和Rand.Uint方法,它们在 Go 1.22 中被遗漏。 - •
ChaCha8.Read方法实现了io.Reader接口。
net
- • 新的
KeepAliveConfig类型允许对 TCP 连接的保持活动选项进行微调。 - •
DNSError类型现在包装由超时或取消引起的错误。 - • 新的
GODEBUG设置netedns0=0禁用在 DNS 请求上发送 EDNS0 附加头。
net/http
- • Cookie 现在会保留围绕 cookie 值的双引号。新的
Cookie.Quoted字段指示Cookie.Value是否原本被引号包围。 - • 新的
Request.CookiesNamed方法检索所有与给定名称匹配的 cookie。 - • 新的
Cookie.Partitioned字段标识具有 Partitioned 属性的 cookie。 - •
ServeMux使用的模式现在允许在方法名后有一个或多个空格或制表符。之前只允许单个空格。 - • 新的
ParseCookie函数解析 Cookie 头值,并返回其中设置的所有 cookie。由于相同的 cookie 名称可以出现多次,因此返回的 Values 可以包含给定键的多个值。 - • 新的
ParseSetCookie函数解析 Set-Cookie 头值并返回一个 cookie。在语法错误时返回错误。 - •
ServeContent、ServeFile和ServeFileFS在服务错误时现在会移除Cache-Control、Content-Encoding、Etag和Last-Modified头。这些头通常适用于非错误内容,而不适用于错误文本。 - • 包裹
ResponseWriter并应用即时编码的中间件(如Content-Encoding: gzip)在此更改后将无法正常工作。可以通过设置GODEBUG=httpservecontentkeepheaders=1来恢复ServeContent、ServeFile和ServeFileFS的先前行为。 - • 对于入站请求,新的
Request.Pattern字段包含匹配的 ServeMux 模式(如果有)。当设置GODEBUG=httpmuxgo121=1时,此字段不会被设置。
net/http/httptest
- • 新的
NewRequestWithContext方法创建一个带有context.Context的入站请求。
net/netip
- • 在 Go 1.22 及更早版本中,使用
reflect.DeepEqual比较持有 IPv4 地址的Addr与持有该地址的 IPv4 映射 IPv6 形式的Addr会错误地返回true,即使使用==或Addr.Compare比较时Addr值是不同的。此错误现已修复,所有三种方法现在报告相同的结果。
os
- •
Stat函数现在为 Windows 上的 Unix 套接字文件设置ModeSocket位。这些文件通过具有设置为IO_REPARSE_TAG_AF_UNIX的重解析标签来标识。 - • 在 Windows 上,
Lstat和Stat报告的 reparse 点的模式位已更改。挂载点不再具有ModeSymlink设置,且不是符号链接、Unix 套接字或重复数据删除文件的 reparse 点现在始终具有ModeIrregular设置。此行为由winsymlink设置控制。对于 Go 1.23,它默认为winsymlink=1。以前版本默认为winsymlink=0。 - •
CopyFS函数将io/fs.FS复制到本地文件系统。 - • 在 Windows 上,
Readlink不再尝试将卷规范化为驱动器字母,这并非总是可行。此行为由winreadlinkvolume设置控制。对于 Go 1.23,它默认为winreadlinkvolume=1。以前版本默认为winreadlinkvolume=0。 - • 在支持 pidfd 的 Linux 上(通常是 Linux v5.4+),与进程相关的函数和方法内部使用 pidfd(而不是 PID),从而消除了当 PID 被操作系统重用时可能发生的潜在错误定位。pidfd 支持对用户完全透明,除了进程可能具有的额外进程文件描述符外。
path/filepath
- • 新的
Localize函数安全地将斜杠分隔的路径转换为操作系统路径。 - • 在 Windows 上,
EvalSymlinks不再评估挂载点,这是许多不一致和错误的根源。此行为由winsymlink设置控制。对于 Go 1.23,它默认为winsymlink=1。以前版本默认为winsymlink=0。 - • 在 Windows 上,
EvalSymlinks不再尝试将卷规范化为驱动器字母,这并非总是可行。此行为由winreadlinkvolume设置控制。对于 Go 1.23,它默认为winreadlinkvolume=1。以前版本默认为winreadlinkvolume=0。
reflect
- • 向
Type添加了与Value中同名方法相对应的新方法: -
- •
Type.OverflowComplex - •
Type.OverflowFloat - •
Type.OverflowInt - •
Type.OverflowUint
- •
- • 新增了
SliceAt函数,其功能类似于NewAt,但适用于切片。 - •
Value.Pointer和Value.UnsafePointer方法现在支持String类型的值。 - • 新增了
Value.Seq和Value.Seq2方法,它们返回序列,这些序列遍历值的方式就像在for/range循环中使用该值一样。 - • 新增了
Type.CanSeq和Type.CanSeq2方法,它们分别报告调用Value.Seq和Value.Seq2是否会成功而不会引发 panic。
runtime/debug
- •
SetCrashOutput函数允许用户指定一个备用文件,运行时应该将其致命崩溃报告写入该文件。这可用于为所有意外崩溃(而不仅仅是那些显式使用recover的 goroutine 中的崩溃)构建自动报告机制。
runtime/pprof
- • 提高了 alloc、mutex、block、threadcreate 和 goroutine 配置文件的最大堆栈深度,从 32 帧增加到 128 帧。
runtime/trace
- • 当程序因未捕获的 panic 而崩溃时,运行时现在会显式刷新跟踪数据。这意味着,如果程序在跟踪活动时崩溃,跟踪中将包含更完整的跟踪数据。
slices
- •
Repeat函数返回一个新的切片,该切片将提供的切片重复给定次数。
sync
- •
Map.Clear方法删除所有条目,导致 Map 为空。这与clear类似。
sync/atomic
- • 新增了
And和Or操作符,它们对给定输入应用按位 AND 或 OR,并返回旧值。
syscall
- • 在 Windows 上,
syscall包现在定义了WSAENOPROTOOPT。 - •
GetsockoptInt函数现在在 Windows 上受支持。
testing/fstest
- •
TestFS现在返回一个结构化错误,该错误可以通过Unwrap()方法(返回[]error)进行解包。这允许使用errors.Is或errors.As来检查错误。
text/template
- • 模板现在支持新的“else with”操作,这在某些用例中可以减少模板的复杂性。
time
- • 如果时区偏移量超出范围,
Parse和ParseInLocation现在将返回错误。
unicode/utf16
- •
RuneLen函数返回 rune 的 UTF-16 编码中的 16 位字数。如果 rune 不是有效的 UTF-16 编码值,则返回 -1。
接口
Darwin
- • 如 Go 1.22 发行说明中所述,Go 1.23 要求 macOS 11 Big Sur 或更高版本;已停止对以前版本的支持。
Linux
- • Go 1.23 是最后一个要求 Linux 内核版本 2.6.32 或更高版本的版本。Go 1.24 将要求 Linux 内核版本 3.17 或更高版本,但有一个例外:如果内核已打补丁以支持
getrandom系统调用,则运行 3.10 或更高版本的系统将继续受支持。
OpenBSD
- • Go 1.23 为 OpenBSD 在 64 位 RISC-V 上添加了实验性支持(
GOOS=openbsd,GOARCH=riscv64)。
ARM64
- • Go 1.23 引入了新的
GOARM64环境变量,该变量在编译时指定 ARM64 架构的最小目标版本。允许的值是v8.{0-9}和v9.{0-5}。这后面可以跟一个选项,指定目标硬件实现的扩展。有效选项是,lse和,crypto。GOARM64环境变量的默认值是v8.0。
RISC-V
- • Go 1.23 引入了新的
GORISCV64环境变量,该变量选择为哪个 RISC-V 用户模式应用程序配置文件进行编译。允许的值是rva20u64和rva22u64。GORISCV64环境变量的默认值是rva20u64。
Wasm
- •
GOROOT/misc/wasm中的 go_wasip1_wasm_exec 脚本已经放弃了对 wasmtime < 14.0.0 版本的支持。