GO 1.25
Go 1.25 发布说明(草案)
Go 1.25 尚未发布。 本文档是正在编写中的发布说明。Go 1.25 预计于 2025 年 8 月发布。
语言变更
Go 1.25 中没有影响 Go 程序的语法变更。然而,在语言规范中,“核心类型”(core types)的概念已被移除,代之以专门的描述性文本。更多信息请参阅相关博客文章。
工具
Go 命令
go build -asan
选项现在默认在程序退出时执行内存泄露检测。如果 C 分配的内存未被释放,且未被任何其他 C 或 Go 分配的内存引用,将报告错误。可通过在运行程序时设置环境变量ASAN_OPTIONS=detect_leaks=0
禁用这些新错误报告。- Go 发行版将包含更少的预构建工具二进制文件。核心工具链二进制文件(如编译器和链接器)仍会包含,但非
build
或test
操作调用的工具将按需由go tool
构建和运行。 - 新增
go.mod ignore
指令,用于指定go
命令应忽略的目录。匹配包模式(如all
或./...
)时,go
命令将忽略这些目录及其子目录中的文件,但这些文件仍会包含在模块 zip 文件中。 - 新增
go doc -http
选项,将启动文档服务器显示请求对象的文档,并在浏览器窗口中打开文档。 - 新增
go version -m -json
选项,将以 JSON 格式打印嵌入给定 Go 二进制文件中的runtime/debug.BuildInfo
结构体。 - 解析模块路径时,
go
命令现在支持使用仓库子目录作为模块根路径,语法为<meta name="go-import" content="root-path vcs repo-url subdir">
,表示root-path
对应版本控制系统vcs
下repo-url
中的subdir
目录。 - 新的工作空间包模式
work
匹配工作空间(原称main
)模块中的所有包:在模块模式下指单个工作模块,在工作空间模式下指所有工作空间模块的集合。 - 当
go
命令更新go.mod
或go.work
文件中的go
行时,不再添加指定当前命令版本的toolchain
行。
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 数量,
GOMAXPROCS
将默认设为该限制值。在 Kubernetes 等容器运行时系统中,cgroup CPU 带宽限制通常对应 “CPU limit” 选项。Go 运行时不考虑 “CPU requests” 选项。 - 所有操作系统:如果可用逻辑 CPU 数量或 cgroup CPU 带宽限制发生变化,运行时会定期更新
GOMAXPROCS
。
如果通过 GOMAXPROCS
环境变量或 runtime.GOMAXPROCS
调用手动设置了 GOMAXPROCS
,则上述行为自动禁用。也可分别通过 GODEBUG
设置 containermaxprocs=0
和 updatemaxprocs=0
显式禁用。
为支持读取更新的 cgroup 限制,运行时将在进程生命周期内缓存 cgroup 文件的文件描述符。
新的实验性垃圾回收器
新增一个实验性垃圾回收器。该回收器设计通过更好的局部性和 CPU 可扩展性提升标记和扫描小对象的性能。基准测试结果各异,但我们预计在重度使用垃圾回收器的实际程序中,垃圾回收开销可减少 10-40%。
构建时设置 GOEXPERIMENT=greenteagc
可启用新垃圾回收器。我们预计该设计将持续演进和改进。为此,我们鼓励 Go 开发者试用并通过 GitHub issue 分享使用体验(含设计详情和反馈指南)。
未处理 panic 输出的变更
因被恢复(recovered)后又重新引发(repanicked)的未处理 panic 导致程序退出时,打印的消息不再重复 panic 值的文本。
先前,一个使用 panic("PANIC")
引发 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
禁用此功能。
编译器
- Go 1.25 中的编译器和链接器现在使用 DWARF 版本 5 生成调试信息。新版 DWARF 减少了 Go 二进制文件中调试信息所需的空间,并缩短了链接时间(尤其对大型 Go 二进制文件)。构建时设置环境变量
GOEXPERIMENT=nodwarf5
可禁用 DWARF 5 生成(此选项未来可能移除)。 - 编译器已修复以确保及时执行 nil 指针检查。像下面这样曾成功运行的程序,现在将因 nil 指针异常而 panic:
此程序错误在于检查package main import "os" func main() {f, err := os.Open("nonExistentFile")name := f.Name() // 错误:应在检查 err 后使用 fif err != nil {return}println(name) }
err
前使用了os.Open
的结果。根据 Go 规范,若error
结果非 nil,则os.Open
的主要结果可能为 nil 指针。但因编译器 bug,该程序在 Go 1.21 至 1.24 下能运行成功(违反 Go 规范)。在 Go 1.25 中将无法成功运行。若此变更影响您的代码,解决方案是将非 nil 错误检查提前(最好紧接在产生错误的语句后)。 - 编译器现在能在更多情况下将切片的底层存储分配在栈上,从而提升性能。此变更可能放大错误使用
unsafe.Pointer
的影响(参见 issue 73199)。为定位此类问题,可使用bisect
工具配合-compile=variablemake
标志查找引发问题的分配。也可通过-gcflags=all=-d=variablemakehash=n
禁用所有此类新的栈分配。
链接器
链接器现在接受 -funcalign=N
命令行选项,用于指定函数入口的对齐方式。默认值依平台而定,本版本中未更改。
标准库
新增 testing/synctest 包
新的 testing/synctest
包为测试并发代码提供支持:
Test
函数在隔离的 “bubble” 中运行测试函数。在 bubble 内,time
包函数操作模拟时钟。Wait
函数等待当前 bubble 中的所有 goroutine 阻塞。
新增实验性 encoding/json/v2 包
Go 1.25 包含新的实验性 JSON 实现,构建时设置环境变量 GOEXPERIMENT=jsonv2
可启用。
启用后,可使用两个新包:
encoding/json/v2
是encoding/json
包的重大修订版。encoding/json/jsontext
提供 JSON 语法的低级处理。
此外,启用 “jsonv2” GOEXPERIMENT 时:
encoding/json
包使用新 JSON 实现。编组(Marshaling)和解组(Unmarshaling)行为不受影响,但包函数返回的错误文本可能变化。encoding/json
包包含许多新选项,可用于配置编组器和解组器。
新实现在许多场景下性能大幅优于现有实现。通常编码性能两者相当,解码性能新实现显著更快。详见 github.com/go-json-experiment/jsonbench 仓库的详细分析。
更多细节参见提案 issue。我们鼓励 encoding/json
用户启用 GOEXPERIMENT=jsonv2
测试程序,以帮助检测与新实现的兼容性问题。
我们预计 encoding/json/v2
的设计将持续演进。鼓励开发者试用新 API 并在提案 issue 中反馈。
库的次要变更
- archive/tar
Writer.AddFS
实现现在支持对实现了io/fs.ReadLinkFS
的文件系统的符号链接。 - crypto
新增MessageSigner
签名接口,供需要自行哈希待签名消息的签名者实现。
新增SignMessage
函数,尝试将Signer
接口更新为MessageSigner
:若成功则使用MessageSigner.SignMessage
方法,否则使用Signer.Sign
。 可用于需同时支持Signer
和MessageSigner
的代码。 - crypto/ecdsa
新增ParseRawPrivateKey
、ParseUncompressedPublicKey
、PrivateKey.Bytes
和PublicKey.Bytes
函数及方法,实现低级编码,替代需使用crypto/elliptic
或math/big
函数/方法的需求。 - crypto/elliptic
某些Curve
实现上隐藏且未文档化的Inverse
和CombinedMult
方法已被移除。 - crypto/sha3
新增SHA3.Clone
方法实现hash.Cloner
。 - crypto/tls
- 新增
ConnectionState.CurveID
字段,公开用于建立连接的密钥交换机制。 - 新增
Config.GetEncryptedClientHelloKeys
回调,供服务器在客户端发送 Encrypted Client Hello 扩展时设置要使用的EncryptedClientHelloKeys
。 - 根据 RFC 9155,TLS 1.2 握手现在禁用 SHA-1 签名算法。可通过
GODEBUG
选项tlssha1=1
重新启用。 - 启用 FIPS 140-3 模式时,TLS 1.2 现在要求使用扩展主密钥(Extended Master Secret),并允许使用 Ed25519 和 X25519MLKEM768。
- TLS 服务器现在优先选择支持的最高协议版本,即使它不是客户端最偏好的版本。
- 新增
- crypto/x509
CreateCertificate
、CreateCertificateRequest
和CreateRevocationList
现在可接受crypto.MessageSigner
签名接口和crypto.Signer
。这允许这些函数使用实现 “一次性” 签名接口的签名者(哈希在签名操作中完成,而非由调用方完成)。
CreateCertificate
现在在SubjectKeyId
缺失时使用截断的 SHA-256 填充。GODEBUG
设置x509sha256skid=0
可恢复为 SHA-1。 - debug/elf
为 RISC-V ELF 解析新增两个常量:PT_RISCV_ATTRIBUTES
和SHT_RISCV_ATTRIBUTES
。 - 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
形式返回结果。 - hash
- 新增
XOF
接口,可由 “可扩展输出函数”(如 SHAKE)实现(具有任意或无限输出长度的哈希函数)。 - 实现新
Cloner
接口的哈希可返回其状态的副本。所有标准库Hash
实现现在均实现Cloner
。
- 新增
- hash/maphash
新增Hash.Clone
方法实现hash.Cloner
。 - io/fs
新增ReadLinkFS
接口,提供读取文件系统中符号链接的能力。 - log/slog
GroupAttrs
从Attr
值切片创建分组Attr
。Record
新增Source
方法,返回其源位置(若不可用则返回 nil)。
- mime/multipart
新增辅助函数FieldContentDisposition
构建 multipart Content-Disposition 头字段。 - net
LookupMX
和Resolver.LookupMX
现在返回看似有效 IP 地址的 DNS 名称以及有效域名。先前若名称服务器返回 IP 地址作为 DNS 名称,LookupMX
会按 RFC 要求丢弃它。但实践中名称服务器有时确实返回 IP 地址。- Windows:
ListenMulticastUDP
现在支持 IPv6 地址。 - Windows:现在支持
os.File
与网络连接之间的转换。具体而言:- 实现了
FileConn
、FilePacketConn
、FileListener
函数,允许获取与打开文件对应的网络连接或监听器。 TCPConn.File
、UDPConn.File
、UnixConn.File
、IPConn.File
、TCPListener.File
和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
)不会阻塞 OS 线程。 - 支持截止时间方法(
File.SetDeadline
、File.SetReadDeadline
、File.SetWriteDeadline
)。
此增强对在 Windows 上通过命名管道通信的应用程序尤其有益。
注意:一个句柄一次只能关联一个完成端口。若提供给
NewFile
的句柄已关联完成端口,返回的File
将降级为同步 I/O 模式(此时 I/O 方法会阻塞 OS 线程,且截止时间方法无效)。 - I/O 方法(
DirFS
和Root.FS
返回的文件系统实现了新的io/fs.ReadLinkFS
接口。当复制实现io/fs.ReadLinkFS
的文件系统时,CopyFS
支持符号链接。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
。
- Windows:
- reflect
新增TypeAssert
函数,允许将Value
直接转换为给定类型的 Go 值。这类似于对Value.Interface
结果使用类型断言,但避免了不必要的内存分配。 - regexp/syntax
\p{name}
和\P{name}
字符类语法现在接受名称Any
、ASCII
、Assigned
、Cn
和LC
,以及 Unicode 类别别名(如\p{Letter}
对应\pL
)。遵循 Unicode TR18,它们现在也使用不区分大小写的名称查找,忽略空格、下划线和连字符。 - runtime
- 由
AddCleanup
调度的清理函数现在并发并行执行,使清理更适用于重负载场景(如unique
包)。注意单个清理若需长时间执行或阻塞,仍应将其工作分流到新 goroutine,以免阻塞清理队列。 - 设置
GODEBUG=checkfinalizers=1
时,运行时将在每个垃圾回收周期运行诊断以查找程序使用终结器(finalizers)和清理的常见问题(如 GC 指南所述)。在此模式下,运行时还会定期将终结器和清理队列长度报告到 stderr,以帮助识别长时间运行的终结器/清理问题。 - 新增
SetDefaultGOMAXPROCS
函数,将GOMAXPROCS
设为运行时默认值(如同未设置GOMAXPROCS
环境变量)。若GOMAXPROCS
环境变量或先前GOMAXPROCS
调用禁用了新GOMAXPROCS
默认行为,此函数可用于重新启用它。
- 由
- runtime/pprof
针对运行时内部锁竞争的互斥锁分析(mutex profile)现在正确指向导致延迟的临界区末尾。这使该部分分析的行为与对sync.Mutex
值竞争的分析保持一致。允许选择 Go 1.22 至 1.24 中此部分分析特殊行为的GODEBUG
设置runtimecontentionstacks
现已移除。 - runtime/trace
新增FlightRecorder
(飞行记录器),提供轻量级方式在特定时刻捕获最近几秒执行的跟踪数据。发生重大事件时,程序可调用FlightRecorder.WriteTo
快照可用跟踪数据。FlightRecorderConfig
可配置FlightRecorder
捕获的时间长度和数据量。 - sync
WaitGroup
新增WaitGroup.Go
方法,使创建和计数 goroutine 的常见模式更便捷。 - testing
- 新增方法
T.Attr
、B.Attr
和F.Attr
,向测试日志发出属性(attribute)。属性是与测试关联的任意键值对。
例如,在名为TestAttr
的测试中,t.Attr("key", "value")
输出:
=== ATTR TestAttr key value
T
、B
和F
的Output
方法提供io.Writer
,写入与TB.Log
相同的测试输出流,但省略文件和行号。- 若有并行测试运行,
AllocsPerRun
函数现在会 panic。AllocsPerRun
的结果在其他测试运行时本质上是不可靠的。新的 panic 行为有助于捕获此类错误。
- 新增方法
- testing/fstest
MapFS
实现新的io/fs.ReadLinkFS
接口。- 若实现
io/fs.ReadLinkFS
接口,TestFS
将验证其功能。 TestFS
不再遵循符号链接以避免无限递归。
- unicode
- 新增
CategoryAliases
映射,提供对类别别名(如 “Letter” 对应 “L”)的访问。 - 新增类别
Cn
(未分配码点)和LC
(大小写字母)。这些始终由 Unicode 定义,但在早期 Go 版本中被无意遗漏。 C
类别现在包含Cn
(即添加了所有未分配码点)。
- 新增
- unique
unique
包现在更积极、更高效且并行地回收(reclaim)内部值(interned values)。因此,在大量真正唯一的值被内部化时,使用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 中移除。
RISC-V
linux/riscv64
移植现在支持 plugin 构建模式。GORISCV64
环境变量现在接受新值rva23u64
,用于选择 RVA23U64 用户模式应用程序配置文件。