Go 1.25 发行说明
Go 1.25 简介
最新的 Go 版本 1.25 将于 2025 年 8 月 发布,比 Go 1.24 晚六个月。其大部分更改都在工具链、运行时和库的实现中。一如既往,此版本保持了 Go 1 的兼容性承诺。我们预计几乎所有 Go 程序都将继续像以前一样编译和运行。
语言变化
Go 1.25 中没有影响 Go 程序的语言更改。然而,在语言规范中,核心类型的概念已被删除,取而代之的是专门的散文。有关更多信息,请参阅相关的博客文章。
工具
Go 命令
go build
-asan
选项现在默认为在程序退出时进行内存泄漏检测。如果 C 分配的内存未释放且未被 C 或 Go 分配的任何其他内存引用,则将报告错误。可以通过在运行程序时在环境中设置 ASAN_OPTIONS=detect_leaks=0
来禁用这些新的错误报告。
Go 发行版将包含更少的预构建工具二进制文件。编译器和链接器等核心工具链二进制文件仍将包含在内,但未通过构建或测试操作调用的工具将根据需要由 go tool
构建和运行。
新的 go.mod
ignore
指令可用于指定 go
命令应忽略的目录。当匹配包模式(如 all
或 ./...
)时,go
命令将忽略这些目录及其子目录中的文件,但它们仍将包含在模块 zip 文件中。
新的 go doc
-http
选项将启动一个文档服务器,显示所请求对象的文档,并在浏览器窗口中打开文档。
新的 go version -m -json
选项将打印给定 Go 二进制文件中嵌入的 runtime/debug.BuildInfo
结构的 JSON 编码。
当使用 <meta name="go-import" content="root-path vcs repo-url subdir">
语法解析模块路径时,go
命令现在支持使用存储库的子目录作为模块根的路径,以指示 root-path
对应于具有版本控制系统 vcs
的 repo-url
的 subdir
。
新的 work
包模式匹配工作(以前称为主)模块中的所有包:模块模式下的单个工作模块或工作区模式下的工作区模块集。
当 go 命令更新 go.mod
或 go.work
文件中的 go
行时,它不再添加指定命令当前版本的工具链行。
Vet
go vet
命令包含新的分析器
- waitgroup,它报告对
sync.WaitGroup.Add
的错位调用;以及
- hostport,它报告使用
fmt.Sprintf("%s:%d", host, port)
构造net.Dial
地址,因为这些地址不适用于 IPv6;相反,它建议使用net.JoinHostPort
。
运行时
容器感知 GOMAXPROCS
GOMAXPROCS
的默认行为已更改。在 Go 的早期版本中,GOMAXPROCS
默认为启动时可用的逻辑 CPU 数量 (runtime.NumCPU
)。Go 1.25 引入了两项更改
-
在 Linux 上,运行时会考虑包含进程的 cgroup 的 CPU 带宽限制(如果有)。如果 CPU 带宽限制低于可用逻辑 CPU 的数量,
GOMAXPROCS
将默认为较低的限制。在 Kubernetes 等容器运行时系统中,cgroup CPU 带宽限制通常对应于“CPU 限制”选项。Go 运行时不考虑“CPU 请求”选项。 -
在所有操作系统上,如果可用逻辑 CPU 数量或 cgroup CPU 带宽限制发生变化,运行时会定期更新
GOMAXPROCS
。
如果通过 GOMAXPROCS
环境变量或调用 runtime.GOMAXPROCS
手动设置 GOMAXPROCS
,则这两种行为都会自动禁用。它们也可以分别通过 GODEBUG 设置 containermaxprocs=0
和 updatemaxprocs=0
显式禁用。
为了支持读取更新的 cgroup 限制,运行时将在进程生命周期内保留 cgroup 文件的缓存文件描述符。
新的实验性垃圾收集器
一个新的垃圾收集器现在作为实验提供。该垃圾收集器的设计通过更好的局部性和 CPU 可伸缩性,提高了标记和扫描小对象的性能。基准测试结果各不相同,但我们预计在大量使用垃圾收集器的实际程序中,垃圾收集开销将减少 10-40%。
可以通过在构建时设置 GOEXPERIMENT=greenteagc
来启用新的垃圾收集器。我们预计该设计将继续发展和改进。为此,我们鼓励 Go 开发人员尝试并报告他们的经验。有关设计和分享反馈的说明的更多详细信息,请参阅 GitHub 问题。
跟踪飞行记录器
运行时执行跟踪长期以来提供了一种强大但昂贵的方式来理解和调试应用程序的低级行为。不幸的是,由于其大小和持续写入执行跟踪的成本,它们通常不适用于调试罕见事件。
新的 runtime/trace.FlightRecorder
API 提供了一种轻量级方式来捕获运行时执行跟踪,方法是持续将跟踪记录到内存环形缓冲区中。当发生重要事件时,程序可以调用 FlightRecorder.WriteTo
将跟踪的最后几秒快照到文件中。这种方法通过使应用程序仅捕获重要的跟踪来生成更小的跟踪。
FlightRecorder
捕获的时间长度和数据量可以在 FlightRecorderConfig
中配置。
未处理恐慌输出的更改
当程序由于未处理的恐慌(已恢复并重新恐慌)而退出时打印的消息不再重复恐慌值文本。
以前,一个程序如果因 panic("PANIC")
而恐慌,恢复恐慌,然后以原始值重新恐慌,则会打印
panic: PANIC [recovered]
panic: PANIC
该程序现在将打印
panic: PANIC [recovered, repanicked]
Linux 上的 VMA 名称
在支持匿名虚拟内存区域 (VMA) 名称 (CONFIG_ANON_VMA_NAME
) 的 Linux 系统上,Go 运行时将使用有关其目的的上下文注释匿名内存映射。例如,堆内存的 [anon: Go: heap]
。这可以通过 GODEBUG 设置 decoratemappings=0
禁用。
编译器
nil
指针错误
此版本修复了 Go 1.21 中引入的编译器错误,该错误可能错误地延迟 nil 指针检查。像以下程序(以前错误地成功执行)现在将(正确地)因 nil-pointer 异常而恐慌
package main
import "os"
func main() {
f, err := os.Open("nonExistentFile")
name := f.Name()
if err != nil {
return
}
println(name)
}
此程序不正确,因为它在使用 os.Open
的结果之前检查了错误。如果 err
不为 nil,则 f
结果可能为 nil,在这种情况下 f.Name()
应该恐慌。然而,在 Go 1.21 到 1.24 版本中,编译器错误地将 nil 检查延迟到错误检查之*后*,导致程序成功执行,违反了 Go 规范。在 Go 1.25 中,它将不再成功运行。如果此更改影响您的代码,解决方案是将非 nil 错误检查放在代码中更早的位置,最好是紧跟在生成错误的语句之后。
DWARF5 支持
Go 1.25 中的编译器和链接器现在使用 DWARF 版本 5 生成调试信息。较新的 DWARF 版本减少了 Go 二进制文件中调试信息所需的空间,并减少了链接时间,特别是对于大型 Go 二进制文件。可以通过在构建时设置环境变量 GOEXPERIMENT=nodwarf5
来禁用 DWARF 5 生成(此回退可能会在未来的 Go 版本中删除)。
更快的切片
编译器现在可以在更多情况下在堆栈上分配切片的后备存储,从而提高性能。此更改有可能放大不正确 unsafe.Pointer 用法的影响,例如 问题 73199。为了跟踪这些问题,可以使用 bisect 工具使用 -compile=variablemake
标志查找导致问题的分配。所有此类新的堆栈分配也可以使用 -gcflags=all=-d=variablemakehash=n
关闭。
链接器
链接器现在接受 -funcalign=N
命令行选项,该选项指定函数入口的对齐方式。默认值与平台相关,在此版本中未更改。
标准库
新的 testing/synctest 包
新的 testing/synctest
包提供了测试并发代码的支持。
Test
函数在隔离的“气泡”中运行测试函数。在气泡内,时间是虚拟化的:time
包函数在假时钟上操作,如果气泡中的所有 goroutine 都被阻塞,则时钟会立即前进。
Wait
函数等待当前气泡中的所有 goroutine 阻塞。
此包最初在 Go 1.24 中作为 GOEXPERIMENT=synctest
提供,API 略有不同。该实验现在已全面推出。如果设置了 GOEXPERIMENT=synctest
,旧 API 仍然存在,但将在 Go 1.26 中删除。
新的实验性 encoding/json/v2 包
Go 1.25 包含一个新的实验性 JSON 实现,可以通过在构建时设置环境变量 GOEXPERIMENT=jsonv2
来启用。
启用后,两个新包可用
encoding/json/v2
包是encoding/json
包的一个主要修订版。encoding/json/jsontext
包提供 JSON 语法的低级处理。
此外,当启用“jsonv2”GOEXPERIMENT 时
encoding/json
包使用新的 JSON 实现。编组和解组行为不受影响,但包函数返回的错误文本可能会更改。encoding/json
包包含许多可用于配置编组器和解组器的新选项。
在许多场景下,新实现的性能显着优于现有实现。通常,编码性能在两个实现之间是平等的,而解码在新实现中则显着更快。有关更详细的分析,请参阅 github.com/go-json-experiment/jsonbench 存储库。
有关更多详细信息,请参阅提案问题。
我们鼓励 encoding/json
的用户启用 GOEXPERIMENT=jsonv2
来测试他们的程序,以帮助检测新实现的任何兼容性问题。
我们预计 encoding/json/v2
的设计将继续发展。我们鼓励开发人员尝试新的 API 并在 提案问题上提供反馈。
对库的微小更改
archive/tar
Writer.AddFS
实现现在支持为实现 io/fs.ReadLinkFS
的文件系统提供符号链接。
encoding/asn1
Unmarshal
和 UnmarshalWithParams
现在更一致地解析 ASN.1 类型 T61String 和 BMPString。这可能会导致以前接受的一些格式错误的编码现在被拒绝。
crypto
MessageSigner
是一个新的签名接口,可以由希望自行哈希要签名的消息的签名者实现。还引入了一个新函数 SignMessage
,它尝试将 Signer
接口升级为 MessageSigner
,如果成功则使用 MessageSigner.SignMessage
方法,否则使用 Signer.Sign
。当代码希望同时支持 Signer
和 MessageSigner
时,可以使用此功能。
程序启动后更改 fips140
GODEBUG 设置现在是一个空操作。以前,它被记录为不允许,并且如果更改可能会导致恐慌。
当不支持 AVX2 指令时,amd64 上的 SHA-1、SHA-256 和 SHA-512 现在速度较慢。自 2015 年以来生产的所有服务器处理器(以及大多数其他处理器)都支持 AVX2。
crypto/ecdsa
新的 ParseRawPrivateKey
、ParseUncompressedPublicKey
、PrivateKey.Bytes
和 PublicKey.Bytes
函数和方法实现了低级编码,取代了使用 crypto/elliptic
或 math/big
函数和方法的需要。
启用 FIPS 140-3 模式后,签名速度现在快四倍,与非 FIPS 模式的性能相匹配。
crypto/ed25519
启用 FIPS 140-3 模式后,签名速度现在快四倍,与非 FIPS 模式的性能相匹配。
crypto/elliptic
已删除某些 Curve
实现中隐藏且未文档化的 Inverse
和 CombinedMult
方法。
crypto/rsa
PublicKey
不再声称模数被视为秘密。VerifyPKCS1v15
和 VerifyPSS
已经警告所有输入都是公开的并且可能泄露,并且存在可以从其他公共值恢复模数的数学攻击。
密钥生成现在快三倍。
crypto/sha1
当 SHA-NI 指令可用时,amd64 上的哈希速度现在快两倍。
crypto/sha3
新的 SHA3.Clone
方法实现了 hash.Cloner
。
在 Apple M 处理器上,哈希速度现在快两倍。
crypto/tls
新的 ConnectionState.CurveID
字段公开了用于建立连接的密钥交换机制。
新的 Config.GetEncryptedClientHelloKeys
回调可用于设置服务器在客户端发送加密客户端 Hello 扩展时使用的 EncryptedClientHelloKey
。
根据 RFC 9155,TLS 1.2 握手现在不允许 SHA-1 签名算法。它们可以通过 GODEBUG 设置 tlssha1=1
重新启用。
当启用 FIPS 140-3 模式时,TLS 1.2 中现在需要扩展主密钥,并且现在允许 Ed25519 和 X25519MLKEM768。
TLS 服务器现在优先选择支持的最高协议版本,即使它不是客户端最喜欢的协议版本。
TLS 客户端和服务器现在都更严格地遵循规范并拒绝不符合规范的行为。与兼容对等方的连接应该不受影响。
crypto/x509
CreateCertificate
、CreateCertificateRequest
和 CreateRevocationList
现在可以接受 crypto.MessageSigner
签名接口以及 crypto.Signer
。这允许这些函数使用实现“一次性”签名接口的签名器,其中哈希作为签名操作的一部分完成,而不是由调用方完成。
CreateCertificate
现在使用截断的 SHA-256 来填充 SubjectKeyId
(如果它缺失)。GODEBUG 设置 x509sha256skid=0
恢复为 SHA-1。
ParseCertificate
现在拒绝包含 BasicConstraints 扩展且包含负 pathLenConstraint 的证书。
ParseCertificate
现在更一致地处理使用 ASN.1 T61String 和 BMPString 类型编码的字符串。这可能会导致以前接受的一些格式错误的编码现在被拒绝。
debug/elf
debug/elf
包添加了两个新常量
PT_RISCV_ATTRIBUTES
SHT_RISCV_ATTRIBUTES
用于 RISC-V ELF 解析。
go/ast
FilterPackage
、PackageExports
和 MergePackageFiles
函数,以及 MergeMode
类型及其常量,都已弃用,因为它们仅用于长期弃用的 Object
和 Package
机制。
新的 PreorderStack
函数,如 Inspect
,遍历语法树并控制下降到子树,但为了方便起见,它还在每个点提供包含节点的堆栈。
go/parser
ParseDir
函数已弃用。
go/token
新的 FileSet.AddExistingFiles
方法允许将现有的 File
添加到 FileSet
,或者为任意一组 File
构造 FileSet
,从而缓解了长期运行的应用程序中单个全局 FileSet
相关的问题。
go/types
Var
现在有一个 Var.Kind
方法,它将变量分类为:包级、接收器、参数、结果、局部变量或结构字段。
新的 LookupSelection
函数查找给定名称和接收器类型的字段或方法,就像现有的 LookupFieldOrMethod
函数一样,但以 Selection
的形式返回结果。
哈希
新的 XOF
接口可以由“可扩展输出函数”实现,这些函数是具有任意或无限输出长度的哈希函数,例如 SHAKE。
实现新 Cloner
接口的哈希可以返回其状态的副本。所有标准库 Hash
实现现在都实现了 Cloner
。
hash/maphash
新的 Hash.Clone
方法实现了 hash.Cloner
。
io/fs
新的 ReadLinkFS
接口提供了在文件系统中读取符号链接的能力。
日志/slog
GroupAttrs
从 Attr
值切片创建组 Attr
。
Record
现在有一个 Source
方法,返回其源位置或 nil(如果不可用)。
mime/multipart
新的辅助函数 FileContentDisposition
构建多部分 Content-Disposition 标头字段。
net
LookupMX
和 Resolver.LookupMX
现在返回看起来像有效 IP 地址的 DNS 名称,以及有效的域名。以前,如果名称服务器返回 IP 地址作为 DNS 名称,LookupMX
会根据 RFC 的要求将其丢弃。然而,实际上名称服务器有时会返回 IP 地址。
在 Windows 上,ListenMulticastUDP
现在支持 IPv6 地址。
在 Windows 上,现在可以在 os.File
和网络连接之间进行转换。具体来说,现在实现了 FileConn
、FilePacketConn
和 FileListener
函数,并返回与打开的文件对应的网络连接或监听器。同样,现在实现了 TCPConn
、UDPConn
、UnixConn
、IPConn
、TCPListener
和 UnixListener
的 File
方法,并返回网络连接的底层 os.File
。
net/http
新的 CrossOriginProtection
通过拒绝不安全的跨域浏览器请求来实现对 跨站请求伪造 (CSRF) 的保护。它使用 现代浏览器 Fetch 元数据,不需要令牌或 Cookie,并支持基于来源和基于模式的绕过。
os
在 Windows 上,NewFile
现在支持为异步 I/O 打开的句柄(即在 syscall.CreateFile
调用中指定了 syscall.FILE_FLAG_OVERLAPPED
)。这些句柄与 Go 运行时的 I/O 完成端口关联,这为生成的 File
提供了以下好处
- I/O 方法(
File.Read
、File.Write
、File.ReadAt
和File.WriteAt
)不会阻塞操作系统线程。 - 支持截止日期方法(
File.SetDeadline
、File.SetReadDeadline
和File.SetWriteDeadline
)。
此增强功能对于通过 Windows 上的命名管道进行通信的应用程序特别有益。
请注意,句柄一次只能与一个完成端口关联。如果提供给 NewFile
的句柄已与完成端口关联,则返回的 File
将降级为同步 I/O 模式。在这种情况下,I/O 方法将阻塞操作系统线程,并且截止日期方法无效。
由 DirFS
和 Root.FS
返回的文件系统实现了新的 io/fs.ReadLinkFS
接口。CopyFS
在复制实现 io/fs.ReadLinkFS
的文件系统时支持符号链接。
Root
类型支持以下附加方法
Root.Chmod
Root.Chown
Root.Chtimes
Root.Lchown
Root.Link
Root.MkdirAll
Root.ReadFile
Root.Readlink
Root.RemoveAll
Root.Rename
Root.Symlink
Root.WriteFile
reflect
新的 TypeAssert
函数允许将 Value
直接转换为给定类型的 Go 值。这类似于对 Value.Interface
的结果使用类型断言,但避免了不必要的内存分配。
regexp/syntax
\p{name}
和 \P{name}
字符类语法现在接受 Any、ASCII、Assigned、Cn 和 LC 名称,以及像 \pL
这样的 Unicode 类别别名 \p{Letter}
。根据 Unicode TR18,它们现在也使用不区分大小写的名称查找,忽略空格、下划线和连字符。
runtime
由 AddCleanup
安排的清理函数现在并发并行执行,使得清理对于像 unique
包这样的繁重使用更可行。请注意,如果单个清理必须长时间执行或阻塞以避免阻塞清理队列,它们仍应将其工作分流到新的 goroutine。
一个新的 GODEBUG=checkfinalizers=1
设置有助于查找 finalizer 和 cleanup 的常见问题,例如 GC 指南中描述的问题。在此模式下,运行时在每个垃圾收集周期运行诊断,并将定期向 stderr 报告 finalizer 和 cleanup 队列长度,以帮助识别长时间运行的 finalizer 和/或 cleanup 的问题。有关更多详细信息,请参阅 GODEBUG 文档。
新的 SetDefaultGOMAXPROCS
函数将 GOMAXPROCS
设置为运行时默认值,就好像未设置 GOMAXPROCS
环境变量一样。这对于启用新的 GOMAXPROCS
默认值很有用,如果它已被 GOMAXPROCS
环境变量或先前对 GOMAXPROCS
的调用禁用。
runtime/pprof
运行时内部锁争用的互斥锁配置文件现在正确指向导致延迟的关键部分的末尾。这与配置文件对于 sync.Mutex
值争用的行为相匹配。GODEBUG
的 runtimecontentionstacks
设置(允许选择 Go 1.22 到 1.24 在此配置文件部分的异常行为)现在已删除。
sync
新的 WaitGroup.Go
方法使得创建和计数 goroutine 的常见模式更加方便。
testing
新的方法 T.Attr
、B.Attr
和 F.Attr
向测试日志发出属性。属性是与测试关联的任意键和值。
例如,在名为 TestF
的测试中,t.Attr("key", "value")
发出
=== ATTR TestF key value
使用 -json
标志,属性显示为新的“attr”操作。
T
、B
和 F
的新 Output
方法提供了一个 io.Writer
,它写入与 TB.Log
相同的测试输出流。与 TB.Log
一样,输出是缩进的,但不包括文件和行号。
如果并行测试正在运行,AllocsPerRun
函数现在会发生恐慌。AllocsPerRun
的结果在其他测试运行时本质上是不稳定的。新的恐慌行为有助于捕获此类错误。
testing/fstest
MapFS
实现了新的 io/fs.ReadLinkFS
接口。TestFS
将验证 io/fs.ReadLinkFS
接口的功能(如果已实现)。TestFS
将不再跟踪符号链接以避免无界递归。
unicode
新的 CategoryAliases
映射提供对类别别名名称的访问,例如“Letter”表示“L”。
新的类别 Cn
和 LC
分别定义了未分配的码点和带大小写的字母。这些始终由 Unicode 定义,但在 Go 的早期版本中无意中省略了。C
类别现在包含 Cn
,这意味着它添加了所有未分配的码点。
独特
unique
包现在更积极、更高效地并行回收内部化值。因此,使用 Make
的应用程序在内部化大量真正唯一值时,内存膨胀的可能性更小。
传递给 Make
的包含 Handle
的值以前需要多个垃圾收集周期才能收集,与 Handle
值链的深度成比例。现在,一旦未使用,它们会在单个周期内迅速收集。
移植
Darwin
正如 Go 1.24 发行说明中宣布的那样,Go 1.25 需要 macOS 12 Monterey 或更高版本。对以前版本的支持已停止。
Windows
Go 1.25 是最后一个包含损坏的 32 位 windows/arm 端口(GOOS=windows
GOARCH=arm
)的版本。它将在 Go 1.26 中删除。
龙芯64
linux/loong64 端口现在支持竞态检测器,使用 runtime.SetCgoTraceback
从 C 代码收集回溯信息,并使用内部链接模式链接 cgo 程序。
RISC-V
linux/riscv64 端口现在支持 plugin
构建模式。
GORISCV64
环境变量现在接受一个新值 rva23u64
,它选择 RVA23U64 用户模式应用程序配置文件。