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 用戶模式應用程序配置文件。