Go 1.21 發行說明

Go 1.21 簡介

最新的 Go 版本 1.21 在 Go 1.20 釋出六個月後到來。它的大部分更改都在工具鏈、執行時和庫的實現中。一如既往,此版本保持了 Go 1 的相容性承諾;事實上,Go 1.21 改進了這一承諾。我們預計幾乎所有 Go 程式都將像以前一樣繼續編譯和執行。

Go 1.21 對版本編號做了一個小改動。過去,我們使用 Go 1.N 來指代整個 Go 語言版本和版本家族,以及該家族的第一個版本。從 Go 1.21 開始,第一個版本現在是 Go 1.N.0。今天我們釋出的是 Go 1.21 語言及其初始實現 Go 1.21.0 版本。這些說明中提到“Go 1.21”;像 go version 這樣的工具將報告“go1.21.0”(直到您升級到 Go 1.21.1)。有關新版本編號的詳細資訊,請參閱“Go 工具鏈”文件中的“Go 版本”。

語言變化

Go 1.21 向語言中添加了三個新的內建函式。

  • 新函式 minmax 計算給定固定數量引數的最小值(或最大值,對於 max)。有關詳細資訊,請參閱語言規範。
  • 新函式 clear 從對映中刪除所有元素或將切片的所有元素歸零。有關詳細資訊,請參閱語言規範。

包初始化順序現在規定得更精確。新演算法是

  • 按匯入路徑對所有包進行排序。
  • 重複直到包列表為空
    • 找到列表中所有匯入都已初始化的第一個包。
    • 初始化該包並將其從列表中刪除。

這可能會改變某些程式行為,如果它們依賴於未透過顯式匯入表達的特定初始化順序。過去版本中,此類程式的行為並未由規範明確定義。新規則提供了明確的定義。

型別推斷方面進行了多項改進,以提高其功能和精確度。

  • (可能是部分例項化的泛型)函式現在可以以自身也是(可能是部分例項化的)泛型函式的引數呼叫。編譯器將嘗試推斷被呼叫者的缺失型別引數(如前所述),對於作為尚未完全例項化的泛型函式的每個引數,也會推斷其缺失的型別引數(新增)。典型的用例是對容器(如 slices.IndexFunc)上的泛型函式進行呼叫,其中函式引數也可能是泛型,並且被呼叫函式及其引數的型別引數是從容器型別推斷出來的。更一般地,如果型別引數可以從賦值中推斷出來,泛型函式現在可以在沒有顯式例項化的情況下使用,當它被賦值給變數或作為結果值返回時。
  • 當一個值被賦值給介面時,型別推斷現在也會考慮方法:方法簽名中使用的型別引數的型別引數可以從匹配方法的相應引數型別中推斷出來。
  • 類似地,由於型別引數必須實現其相應約束的所有方法,因此會匹配型別引數和約束的方法,這可能導致推斷出額外的型別引數。
  • 如果不同型別的多個無型別常量引數(例如無型別 int 和無型別浮點常量)傳遞給具有相同(未另行指定)型別引數型別的引數,現在型別推斷會使用與具有無型別常量運算元的運算子相同的方法來確定型別,而不是報告錯誤。此更改使從無型別常量引數推斷的型別與常量表達式的型別保持一致。
  • 型別推斷在賦值中匹配相應型別時現在是精確的:元件型別(例如切片的元素,或函式簽名中的引數型別)必須相同(給定合適的型別引數)才能匹配,否則推斷失敗。此更改會產生更準確的錯誤訊息:過去型別推斷可能錯誤地成功並導致無效賦值,而現在如果兩種型別不可能匹配,編譯器會報告推斷錯誤。

更一般地,語言規範中關於型別推斷的描述已得到澄清。總之,所有這些更改使型別推斷更強大,推斷失敗更不意外。

Go 1.21 包含我們正在考慮在未來 Go 版本中進行的語言更改的預覽:使 for 迴圈變數為每次迭代一次,而不是每次迴圈一次,以避免意外的共享錯誤。有關如何嘗試該語言更改的詳細資訊,請參閱 LoopvarExperiment wiki 頁面

Go 1.21 現在定義:如果一個 goroutine 正在 panic 並且 recover 被 deferred 函式直接呼叫,則 recover 的返回值保證不為 nil。為了確保這一點,使用 nil 介面值(或無型別 nil)呼叫 panic 會導致 *runtime.PanicNilError 型別的執行時 panic。

為了支援為舊版本 Go 編寫的程式,可以透過設定 GODEBUG=panicnil=1 重新啟用 nil panics。當編譯其主包在宣告 go 1.20 或更早版本的模組中的程式時,此設定會自動啟用。

工具

Go 1.21 增加了對 Go 工具鏈中向後相容性和向前相容性的改進支援。

為了提高向後相容性,Go 1.21 正式化了 Go 對 GODEBUG 環境變數的使用,以控制根據相容性策略不構成破壞性更改但仍可能導致現有程式中斷的更改的預設行為。(例如,依賴於錯誤行為的程式在錯誤修復時可能會中斷,但錯誤修復不被視為破壞性更改。)當 Go 必須進行這種行為更改時,它現在根據工作區 go.work 檔案或主模組 go.mod 檔案中的 go 行選擇舊行為和新行為。升級到新的 Go 工具鏈但將 go 行設定為其原始(較舊)Go 版本會保留舊工具鏈的行為。有了這種相容性支援,最新的 Go 工具鏈應該始終是舊版本 Go 的最佳、最安全的實現。有關詳細資訊,請參閱“Go、向後相容性和 GODEBUG”。

為了提高向前相容性,Go 1.21 現在將 go.workgo.mod 檔案中的 go 行讀取為嚴格的最低要求:go 1.21.0 意味著工作區或模組不能與 Go 1.20 或 Go 1.21rc1 一起使用。這允許依賴於 Go 後續版本中修復的專案確保它們不與早期版本一起使用。它還為使用新 Go 功能的專案提供了更好的錯誤報告:當問題是需要更新的 Go 版本時,會清楚地報告該問題,而不是嘗試構建程式碼並列印有關未解析匯入或語法錯誤的錯誤。

為了更容易管理這些新的更嚴格的版本要求,go 命令現在不僅可以呼叫其自身版本中捆綁的工具鏈,還可以呼叫在 PATH 中找到或按需下載的其他 Go 工具鏈版本。如果 go.modgo.work go 行聲明瞭對較新 Go 版本的最低要求,go 命令將自動查詢並執行該版本。新的 toolchain 指令設定了建議使用的最低工具鏈,該工具鏈可能比嚴格的 go 最低要求更新。有關詳細資訊,請參閱“Go 工具鏈”。

Go 命令

-pgo 構建標誌現在預設為 -pgo=auto,並且刪除了在命令列上指定單個主包的限制。如果主包目錄中存在名為 default.pgo 的檔案,go 命令將使用它來為構建相應程式啟用配置檔案引導最佳化。

-C dir 標誌在使用時現在必須是命令列上的第一個標誌。

新的 go test 選項 -fullpath 在測試日誌訊息中列印完整路徑名,而不是僅列印基本名稱。

go test -c 標誌現在支援為多個包編寫測試二進位制檔案,每個檔案都寫入 pkg.test,其中 pkg 是包名。如果正在編譯的多個測試包具有給定的包名,則會出錯。

go test -o 標誌現在接受目錄引數,在這種情況下,測試二進位制檔案會寫入該目錄而不是當前目錄。

當使用外部 (C) 連結器並啟用 cgo 時,runtime/cgo 包現在作為附加依賴項提供給 Go 連結器,以確保 Go 執行時與 C 連結器新增的任何附加庫相容。

Cgo

import "C" 的檔案中,Go 工具鏈現在正確報告嘗試在 C 型別上宣告 Go 方法的錯誤。

執行時

在列印非常深的堆疊時,執行時現在列印前 50 個(最內層)幀,然後是後 50 個(最外層)幀,而不是隻列印前 100 個幀。這使得更容易檢視深度遞迴堆疊是如何開始的,對於除錯堆疊溢位尤其有價值。

在支援透明大頁的 Linux 平臺上,Go 執行時現在更明確地管理堆的哪些部分可能由大頁支援。這導致記憶體利用率更高:小堆應該使用更少的記憶體(在病態情況下最多 50%),而大堆應該在堆的密集部分看到更少損壞的大頁,從而將 CPU 使用率和延遲提高多達 1%。此更改的一個結果是執行時不再嘗試解決特定的有問題 Linux 配置設定,這可能導致更高的記憶體開銷。推薦的修復方法是根據GC 指南調整作業系統的大頁設定。但是,也有其他解決方法。請參閱關於 max_ptes_none部分

由於執行時內部垃圾收集調整,應用程式的尾部延遲可能會減少多達 40%,並且記憶體使用量略有減少。一些應用程式也可能會觀察到吞吐量略有下降。記憶體使用量的減少應該與吞吐量的損失成比例,這樣可以透過稍微增加 GOGC 和/或 GOMEMLIMIT 來恢復上一個版本的吞吐量/記憶體權衡(對延遲幾乎沒有變化)。

從 C 建立的執行緒到 Go 的呼叫需要一些設定來為 Go 執行做準備。在 Unix 平臺上,此設定現在在同一執行緒的多個呼叫中得以保留。這顯著減少了後續 C 到 Go 呼叫的開銷,從每次呼叫約 1-3 微秒降至每次呼叫約 100-200 納秒。

編譯器

配置檔案引導最佳化 (PGO),在 Go 1.20 中作為預覽版新增,現在已可供通用使用。PGO 對生產工作負載配置檔案中標識為“熱點”的程式碼啟用額外的最佳化。如Go 命令部分所述,對於主包目錄中包含 default.pgo 配置檔案的二進位制檔案,PGO 預設啟用。效能改進因應用程式行為而異,大多數代表性 Go 程式集中的程式透過啟用 PGO 獲得了 2% 到 7% 的改進。有關詳細文件,請參閱 PGO 使用者指南

PGO 構建現在可以對某些介面方法呼叫進行去虛擬化,為主常見的被呼叫者新增具體呼叫。這啟用了進一步的最佳化,例如內聯被呼叫者。

Go 1.21 將構建速度提高了 6%,這主要歸功於使用 PGO 構建編譯器本身。

彙編器

在 amd64 上,無幀的 nosplit 彙編函式不再自動標記為 NOFRAME。相反,如果需要,必須明確指定 NOFRAME 屬性,這已經是支援幀指標的其他架構上的行為。透過此更改,執行時現在為堆疊轉換維護幀指標。

檢查 amd64 上動態連結時 R15 不正確使用情況的驗證器已得到改進。

連結器

在 windows/amd64 上,連結器(在編譯器的幫助下)現在預設發出 SEH unwinding 資料,這改進了 Go 應用程式與 Windows 偵錯程式和其他工具的整合。

在 Go 1.21 中,連結器(在編譯器的幫助下)現在能夠刪除死的(未引用的)全域性對映變數,如果變數初始化器中的條目數量足夠大,並且如果初始化器表示式沒有副作用。

標準庫

新的 log/slog 包

新的 log/slog 包提供帶有級別的結構化日誌記錄。結構化日誌記錄發出鍵值對,以實現對大量日誌資料的快速、準確處理。該包支援與流行的日誌分析工具和服務的整合。

新的 testing/slogtest 包

新的 testing/slogtest 包可以幫助驗證 slog.Handler 實現。

新的 slices 包

新的 slices 包提供了許多常見的切片操作,使用適用於任何元素型別切片的泛型函式。

新的 maps 包

新的 maps 包提供了幾種常見的對映操作,使用適用於任何鍵或元素型別對映的泛型函式。

新的 cmp 包

新的 cmp 包定義了型別約束 Ordered 和兩個新的泛型函式 LessCompare,它們對有序型別很有用。

對庫的微小更改

一如既往,庫中進行了各種小的更改和更新,始終牢記 Go 1 的相容性承諾。還有各種未在此處列出的效能改進。

archive/tar

Header.FileInfo 返回的 io/fs.FileInfo 介面的實現現在實現了呼叫 io/fs.FormatFileInfoString 方法。

archive/zip

FileHeader.FileInfo 返回的 io/fs.FileInfo 介面的實現現在實現了呼叫 io/fs.FormatFileInfoString 方法。

Reader.Open 返回的 io/fs.Fileio/fs.ReadDirFile.ReadDir 方法返回的 io/fs.DirEntry 介面的實現現在實現了呼叫 io/fs.FormatDirEntryString 方法。

bytes

Buffer 型別有兩個新方法:AvailableAvailableBuffer。這些方法可以與 Write 方法一起使用,直接追加到 Buffer

context

新的 WithoutCancel 函式返回一個上下文的副本,當原始上下文被取消時,該副本不會被取消。

新的 WithDeadlineCauseWithTimeoutCause 函式提供了一種在截止日期或計時器到期時設定上下文取消原因的方法。原因可以透過 Cause 函式檢索。

新的 AfterFunc 函式註冊一個函式,以便在上下文取消後執行。

一項最佳化意味著呼叫 BackgroundTODO 並將其轉換為共享型別的結果可以被認為是相等的。在以前的版本中,它們總是不同的。比較 Context 值是否相等從未得到明確定義,因此這不被視為不相容的更改。

crypto/ecdsa

PublicKey.EqualPrivateKey.Equal 現在以恆定時間執行。

crypto/elliptic

所有 Curve 方法以及 GenerateKeyMarshalUnmarshal 都已棄用。對於 ECDH 操作,應改用新的 crypto/ecdh 包。對於更低階的操作,請使用第三方模組,例如 filippo.io/nistec

crypto/rand

crypto/rand 包現在在 NetBSD 10.0 及更高版本上使用 getrandom 系統呼叫。

crypto/rsa

對於 GOARCH=amd64GOARCH=arm64,私有 RSA 操作(解密和簽名)的效能現在優於 Go 1.19。它在 Go 1.20 中有所退步。

由於在 PrecomputedValues 中添加了私有欄位,因此即使反序列化(例如從 JSON)以前預計算的私鑰,也必須呼叫 PrivateKey.Precompute 以獲得最佳效能。

PublicKey.EqualPrivateKey.Equal 現在以恆定時間執行。

GenerateMultiPrimeKey 函式和 PrecomputedValues.CRTValues 欄位已棄用。PrecomputedValues.CRTValues 在呼叫 PrivateKey.Precompute 時仍將填充,但這些值在解密操作期間不會使用。

crypto/sha256

SHA-224 和 SHA-256 操作在 GOARCH=amd64 時現在會使用可用的原生指令,提供大約 3-4 倍的效能提升。

crypto/tls

伺服器現在會跳過驗證客戶端證書(包括不執行 Config.VerifyPeerCertificate),對於已恢復的連線,除了檢查過期時間。這使得在使用客戶端證書時會話票據更大。客戶端已經跳過恢復時的驗證,但即使設定了 Config.InsecureSkipVerify,現在也會檢查過期時間。

應用程式現在可以控制會話票據的內容。

為了減少會話票據被用作跨連線跟蹤機制的可能性,伺服器現在在每次恢復時(如果支援且未停用)都會發出新的票據,並且票據不再帶有加密它們的金鑰的識別符號。如果向 Conn.SetSessionTicketKeys 傳遞大量金鑰,這可能會導致顯著的效能開銷。

客戶端和伺服器現在都實現了擴充套件主金鑰擴充套件 (RFC 7627)。ConnectionState.TLSUnique 的棄用已被撤銷,並且現在為支援擴充套件主金鑰的已恢復連線設定。

新的 QUICConn 型別支援 QUIC 實現,包括 0-RTT 支援。請注意,這本身並不是 QUIC 實現,並且 TLS 中仍然不支援 0-RTT。

新的 VersionName 函式返回 TLS 版本號的名稱。

伺服器因客戶端認證失敗而傳送的 TLS 警報程式碼已得到改進。以前,這些失敗總是導致“壞證書”警報。現在,某些失敗將導致更合適的警報程式碼,如 RFC 5246 和 RFC 8446 定義。

  • 對於 TLS 1.3 連線,如果伺服器配置為使用 RequireAnyClientCertRequireAndVerifyClientCert 要求客戶端身份驗證,並且客戶端未提供任何證書,則伺服器現在將返回“需要證書”警報。
  • 如果客戶端提供的證書未由伺服器配置的受信任證書頒發機構集簽名,伺服器將返回“未知證書頒發機構”警報。
  • 如果客戶端提供的證書已過期或尚未生效,伺服器將返回“證書過期”警報。
  • 在所有其他與客戶端身份驗證失敗相關的場景中,伺服器仍返回“壞證書”。

crypto/x509

RevocationList.RevokedCertificates 已棄用,並替換為新的 RevokedCertificateEntries 欄位,它是一個 RevocationListEntry 的切片。RevocationListEntry 包含 pkix.RevokedCertificate 中的所有欄位,以及吊銷原因程式碼。

名稱約束現在在非葉證書上正確執行,而不是在它們表達的證書上執行。

debug/elf

新的 File.DynValue 方法可用於檢索給定動態標籤列出的數值。

DT_FLAGS_1 動態標籤中允許的常量標誌現在定義為 DynFlag1 型別。這些標籤的名稱以 DF_1 開頭。

該包現在定義了常量 COMPRESS_ZSTD

該包現在定義了常量 R_PPC64_REL24_P9NOTOC

debug/pe

嘗試使用 Section.Data 或透過 Section.Open 返回的讀取器從包含未初始化資料的節中讀取,現在會返回錯誤。

embed

FS.Open 返回的 io/fs.File 現在有一個實現了 io.ReaderAtReadAt 方法。

呼叫 FS.Open.Stat 將返回一個現在實現了呼叫 io/fs.FormatFileInfoString 方法的型別。

encoding/binary

新的 NativeEndian 變數可用於使用當前機器的本機位元組序在位元組切片和整數之間進行轉換。

errors

新的 ErrUnsupported 錯誤提供了一種標準化方式來指示所請求的操作可能無法執行,因為它不受支援。例如,當使用不支援硬連結的檔案系統時,呼叫 os.Link

flag

新的 BoolFunc 函式和 FlagSet.BoolFunc 方法定義了一個不需要引數並在使用該標誌時呼叫函式的標誌。這類似於 Func,但適用於布林標誌。

如果已經對同名標誌呼叫了 Set,則標誌定義(透過 BoolBoolVarIntIntVar 等)將引發 panic。此更改旨在檢測因初始化順序更改導致標誌操作以不同於預期順序發生的情況。在許多情況下,此問題的解決方法是引入顯式包依賴項,以在任何 Set 操作之前正確排序定義。

go/ast

新的 IsGenerated 謂詞報告檔案語法樹是否包含通常表示該檔案是由工具生成的特殊註釋

新的 File.GoVersion 欄位記錄了任何 //go:build// +build 指令所需的最低 Go 版本。

go/build

該包現在解析檔案頭(在 package 宣告之前)中的構建指令(以 //go: 開頭的註釋)。這些指令在新的 Package 欄位 DirectivesTestDirectivesXTestDirectives 中可用。

go/build/constraint

新的 GoVersion 函式返回構建表示式所隱含的最低 Go 版本。

go/token

新的 File.Lines 方法以與 File.SetLines 接受的相同形式返回檔案的行號表。

go/types

新的 Package.GoVersion 方法返回用於檢查包的 Go 語言版本。

hash/maphash

hash/maphash 包現在有一個純 Go 實現,可以透過 purego 構建標籤選擇。

html/template

當動作出現在 JavaScript 模板字面量中時,會返回新的錯誤 ErrJSTemplate。以前會返回一個未匯出的錯誤。

io/fs

新的 FormatFileInfo 函式返回 FileInfo 的格式化版本。新的 FormatDirEntry 函式返回 DirEntry 的格式化版本。由 ReadDir 返回的 DirEntry 實現現在實現了一個呼叫 FormatDirEntryString 方法,DirEntry 值傳遞給 WalkDirFunc 也是如此。

math/big

新的 Int.Float64 方法返回多精度整數最接近的浮點值,以及任何發生的舍入指示。

net

在 Linux 上,如果核心支援多路徑 TCP,net 包現在可以使用它。它預設不使用。要在客戶端上可用時使用多路徑 TCP,請在呼叫 Dialer.DialDialer.DialContext 方法之前呼叫 Dialer.SetMultipathTCP 方法。要在伺服器上可用時使用多路徑 TCP,請在呼叫 ListenConfig.Listen 方法之前呼叫 ListenConfig.SetMultipathTCP 方法。像往常一樣指定網路為 "tcp""tcp4""tcp6"。如果核心或遠端主機不支援多路徑 TCP,連線將靜默回退到 TCP。要測試特定連線是否正在使用多路徑 TCP,請使用 TCPConn.MultipathTCP 方法。

在未來的 Go 版本中,我們可能會在支援多路徑 TCP 的系統上預設啟用它。

net/http

新的 ResponseController.EnableFullDuplex 方法允許伺服器處理程式在寫入響應的同時併發讀取 HTTP/1 請求正文。通常,HTTP/1 伺服器在開始寫入響應之前會自動消耗任何剩餘的請求正文,以避免客戶端在讀取響應之前嘗試寫入完整請求時發生死鎖。EnableFullDuplex 方法會停用此行為。

當伺服器使用 HTTP 響應 HTTPS 請求時,ClientTransport 會返回新的 ErrSchemeMismatch 錯誤。

net/http 包現在支援 errors.ErrUnsupported,即表示式 errors.Is(http.ErrNotSupported, errors.ErrUnsupported) 將返回 true。

os

程式現在可以將一個空的 time.Time 值傳遞給 Chtimes 函式,以使訪問時間或修改時間保持不變。

在 Windows 上,File.Chdir 方法現在會將當前目錄更改為檔案,而不是總是返回錯誤。

在 Unix 系統上,如果將非阻塞描述符傳遞給 NewFile,呼叫 File.Fd 方法現在將返回一個非阻塞描述符。以前,描述符會轉換為阻塞模式。

在 Windows 上,對不存在的檔案呼叫 Truncate 曾經會建立一個空檔案。它現在返回一個錯誤,指示該檔案不存在。

在 Windows 上,呼叫 TempDir 現在在可用時使用 GetTempPath2W,而不是 GetTempPathW。新行為是一種安全強化措施,可防止以 SYSTEM 許可權執行的程序建立的臨時檔案被非 SYSTEM 程序訪問。

在 Windows 上,os 包現在支援處理其名稱(儲存為 UTF-16)無法表示為有效 UTF-8 的檔案。

在 Windows 上,Lstat 現在會解析以路徑分隔符結尾的路徑的符號連結,這與其在 POSIX 平臺上的行為一致。

ReadDir 函式和 File.ReadDir 方法返回的 io/fs.DirEntry 介面的實現現在實現了一個呼叫 io/fs.FormatDirEntryString 方法。

DirFS 函式返回的 io/fs.FS 介面的實現現在實現了 io/fs.ReadFileFSio/fs.ReadDirFS 介面。

path/filepath

傳遞給 WalkDir 的函式引數的 io/fs.DirEntry 介面的實現現在實現了呼叫 io/fs.FormatDirEntryString 方法。

reflect

在 Go 1.21 中,ValueOf 不再強制將其引數分配到堆上,允許 Value 的內容分配在堆疊上。對 Value 的大多數操作也允許底層值分配在堆疊上。

新的 Value 方法 Value.Clear 清除對映的內容或將切片的內容歸零。這對應於新增到語言中的新內建函式 clear

SliceHeaderStringHeader 型別現在已棄用。在新程式碼中,優先使用 unsafe.Sliceunsafe.SliceDataunsafe.Stringunsafe.StringData

regexp

Regexp 現在定義了 MarshalTextUnmarshalText 方法。這些方法實現了 encoding.TextMarshalerencoding.TextUnmarshaler,並將被諸如 encoding/json 等包使用。

runtime

Go 程式生成的文字堆疊跟蹤,例如崩潰時、呼叫 runtime.Stack 或使用 debug=2 收集 goroutine 配置檔案時生成的堆疊跟蹤,現在包含建立堆疊跟蹤中每個 goroutine 的 goroutine ID。

崩潰的 Go 應用程式現在可以透過設定環境變數 GOTRACEBACK=wer 或在崩潰前呼叫 debug.SetTraceback("wer") 來選擇加入 Windows 錯誤報告 (WER)。除了啟用 WER,執行時行為將與 GOTRACEBACK=crash 相同。在非 Windows 系統上,GOTRACEBACK=wer 被忽略。

GODEBUG=cgocheck=2,一個嚴格的 cgo 指標傳遞規則檢查器,不再作為除錯選項提供。相反,它作為一項實驗,透過 GOEXPERIMENT=cgocheck2 提供。這意味著此模式必須在構建時而不是啟動時選擇。

GODEBUG=cgocheck=1 仍然可用(並且仍然是預設值)。

執行時包中添加了一個新型別 PinnerPinner 可用於“固定”Go 記憶體,以便非 Go 程式碼可以更自由地使用它。例如,現在允許將引用固定 Go 記憶體的 Go 值傳遞給 C 程式碼。以前,cgo 指標傳遞規則不允許傳遞任何此類巢狀引用。有關詳細資訊,請參閱文件

runtime/metrics

一些以前內部的 GC 指標,例如活動堆大小,現在可用。GOGCGOMEMLIMIT 現在也可用作指標。

runtime/trace

在 amd64 和 arm64 上收集 trace 現在產生的 CPU 開銷顯著降低:比上一個版本改進了多達 10 倍。

trace 現在包含 Go 執行時可能停止世界的所有原因的顯式停止世界事件,而不僅僅是垃圾回收。

sync

新的 OnceFuncOnceValueOnceValues 函式捕獲了 Once 的常見用法,用於在首次使用時惰性初始化值。

syscall

在 Windows 上,Fchdir 函式現在將當前目錄更改為其引數,而不是總是返回錯誤。

在 FreeBSD 上,SysProcAttr 有一個新欄位 Jail,可用於將新建立的程序放入監獄環境中。

在 Windows 上,syscall 包現在支援處理其名稱(儲存為 UTF-16)無法表示為有效 UTF-8 的檔案。UTF16ToStringUTF16FromString 函式現在在 UTF-16 資料和 WTF-8 字串之間進行轉換。這是向後相容的,因為 WTF-8 是早期版本中使用的 UTF-8 格式的超集。

幾個錯誤值與新的 errors.ErrUnsupported 匹配,因此 errors.Is(err, errors.ErrUnsupported) 返回 true。

  • ENOSYS
  • ENOTSUP
  • EOPNOTSUPP
  • EPLAN9 (僅限 Plan 9)
  • ERROR_CALL_NOT_IMPLEMENTED (僅限 Windows)
  • ERROR_NOT_SUPPORTED (僅限 Windows)
  • EWINDOWS (僅限 Windows)

testing

新的 -test.fullpath 選項將在測試日誌訊息中列印完整路徑名,而不是僅列印基本名稱。

新的 Testing 函式報告程式是否是由 go test 建立的測試。

testing/fstest

呼叫 Open.Stat 將返回一個現在實現了呼叫 io/fs.FormatFileInfoString 方法的型別。

unicode

unicode 包和整個系統中的相關支援已升級到 Unicode 15.0.0

移植

Darwin

如 Go 1.20 發行說明中宣佈,Go 1.21 需要 macOS 10.15 Catalina 或更高版本;對先前版本的支援已停止。

Windows

如 Go 1.20 發行說明中宣佈,Go 1.21 至少需要 Windows 10 或 Windows Server 2016;對先前版本的支援已停止。

ARM

當在非 ARM 系統上使用 GOARCH=arm 構建 Go 分發版時(即,當構建一個交叉編譯器到 ARM 時),GOARM 環境變數的預設值現在總是設定為 7。以前的預設值取決於構建系統的特性。

當不構建交叉編譯器時,預設值由檢查構建系統確定。這在 Go 1.21 之前和現在都適用。變化的是在構建交叉編譯器時的行為。

WebAssembly

新的 go:wasmimport 指令現在可以在 Go 程式中用於從 WebAssembly 主機匯入函式。

Go 排程器現在與 JavaScript 事件迴圈的互動效率更高,尤其是在頻繁阻塞非同步事件的應用程式中。

WebAssembly 系統介面

Go 1.21 添加了對 WebAssembly 系統介面 (WASI) 預覽版 1 (GOOS=wasip1, GOARCH=wasm) 的實驗性移植。

由於添加了新的 GOOS 值“wasip1”,除了正在使用該 GOOS 值的情況外,Go 工具現在將忽略名為 *_wasip1.go 的 Go 檔案。如果您有匹配該模式的現有檔名,則需要重新命名它們。

ppc64/ppc64le

在 Linux 上,GOPPC64=power10 現在生成 PC 相對指令、字首指令和其他新的 Power10 指令。在 AIX 上,GOPPC64=power10 生成 Power10 指令,但不生成 PC 相對指令。

當為 GOPPC64=power10 GOOS=linux GOARCH=ppc64le 構建位置獨立二進位制檔案時,使用者在大多數情況下可以期待更小的二進位制檔案大小,某些情況下可減少 3.5%。位置獨立二進位制檔案使用以下 -buildmode 值針對 ppc64le 構建:c-archivec-sharedsharedpieplugin

loong64

linux/loong64 埠現在支援 -buildmode=c-archive-buildmode=c-shared-buildmode=pie