Go 1.20 版本說明

Go 1.20 簡介

最新版本 Go 1.20 於 Go 1.19 發布後六個月推出。其大部分修改之處在於工具鏈、執行時間和程式庫的實作。和過往相同,此版本維持 Go 1 相容性承諾。我們預期幾乎所有 Go 程式都能像以前一樣繼續編譯和執行。

語言變更

Go 1.20 包含四項語言變更。

Go 1.17 新增了 從切片到陣列指標的轉換。Go 1.20 將其延伸,允許從切片轉換到陣列:針對切片 x,現在可以撰寫 [4]byte(x),而不必撰寫 *(*[4]byte)(x)

unsafe 套件 定義了三個新函式,即 SliceDataStringStringData。加上 Go 1.17 的 Slice,這些函式現在提供建構和解構切片和字串值而不依賴其精確表示式的完整功能。

規格現已定義結構值一次比較一個欄位,按照欄位在結構類型定義中出現的順序考慮欄位,並在第一個不匹配時停止。這個規格以前可能被讀成需要在第一個不匹配之後比較所有欄位。類似地,規格現已定義陣列值一次比較一個元素,依據遞增的 index 順序。在兩個情況下,差異在於是否特定比較必須誘發 panic。現有的程式不變:新的規格說明描述了執行項始終執行的動作。

可比較類型(例如一般介面)現在可以滿足 comparable 約束,即使類型引數不完全可比較(比較在執行時會誘發 panic)。這使得可以使用不完全可比較類型引數(例如介面類型或包含介面類型的複合類型)實例化受限於 comparable 的類型參數(例如使用者定義的通用映射金鑰的類型參數)。

Windows

Go 1.20 是最後一個會在任何 Windows 7、8、Server 2008 和 Server 2012 版本上執行的版本。Go 1.21 至少需要 Windows 10 或 Server 2016。

Darwin 與 iOS

Go 1.20 是最後一個會在 macOS 10.13 High Sierra 或 10.14 Mojave 上執行的版本。Go 1.21 需要 macOS 10.15 Catalina 或更新版本。

FreeBSD/RISC-V

Go 1.20 為 FreeBSD 在 RISC-V (GOOS=freebsdGOARCH=riscv64) 上新增實驗支援。

工具

Go 命令

目錄 $GOROOT/pkg 不再儲存標準程式庫的預先編譯套件封存:go install 不再寫入它們,go build 不再檢查它們,而 Go distribution 不再傳送它們。取而代之的是,標準程式庫中的套件會根據需要建立,並快取在建置快取中,就像 GOROOT 之外的套件一樣。這個變更減小了 Go distribution 的大小,並避免使用 cgo 的套件發生 C toolchain skew。

go test -json 的實作已獲得改善,使其更強健。執行 go test -json 的程式不需要任何更新。直接呼叫 go tool test2json 的程式現在應使用 -v=test2json(例如,go test -v=test2json./pkg.test -test.v=test2json)而不是純粹的 -v 來執行測試二進位檔。

go test -json 相關的變更,是在每個測試程式執行開始時候新增一個 Action 設定為 start 的事件。當使用 go 指令執行多項測試時,這些開始事件保證會按照指令列上指定套件的順序傳送。

go 指令現已定義架構功能建置標記,例如 amd64.v2,用來根據特定架構功能的存在或不存在來選取套件實作檔案。詳情請參閱 go help buildconstraint

go 子指令現接受 -C <dir>,在執行指令前變更目錄至 <dir>,這可能對需要在多個不同模組中執行指令的指令碼很實用。

go buildgo test 指令不再接受 -i 標記,自 Go 1.16 起此標記已 不建議使用

go generate 指令現接受 -skip <pattern>,用來略過與 <pattern> 相符的 //go:generate 指示碼。

go test 指令現接受 -skip <pattern>,用來略過與 <pattern> 相符的測試、子測試或範例。

在主模組位於 GOPATH/src 中時,go install 不會再將非 main 套件的函式庫安裝到 GOPATH/pkg,而 go list 也不再為此類套件回報 Target 欄位。(在模組模式中,已編譯的套件只儲存在 建置快取中,但 一個 bug 導致 GOPATH 安裝目標意外生效。)

go buildgo install 和其他與建置相關的指令現支援 -pgo 標記,可用來啟用個人資料引導最佳化,詳細內容請參閱下方 編譯器 區段。-pgo 標記會指定個人資料的檔案路徑。指定 -pgo=auto 會使 go 指令在主套件目錄中搜尋名為 default.pgo 的檔案,並在找到時使用。目前此模式需要在指令列上指定單一主套件,但我們計畫在未來版本解除此限制。指定 -pgo=off 會關閉個人資料引導最佳化。

go buildgo install 和其他與建置相關的指令現支援 -cover 標記,可以用來建置指定目標,且附有程式碼涵蓋工具。詳細內容請參閱下方 涵蓋範圍 區段。

go version

go version -m 指令現支援讀取更多類型的 Go 二進位檔案,最值得注意的是使用 go build -buildmode=c-shared 建置的 Windows DLL 以及沒有執行權限的 Linux 二進位檔。

Cgo

go 命令現在預設在系統中沒有 C 工具鏈的情況下停用 cgo。更具體地說,當 CGO_ENABLED 環境變數是未設定的,CC 環境變數是未設定的,而且在路徑中找不到預設 C 編譯器(通常是 clanggcc)時,CGO_ENABLED 預設為 0。一如往常,您可以透過明確設定 CGO_ENABLED 來覆寫預設值。

預設變更最重要的影響在於,當 Go 安裝在沒有 C 編譯器的系統上時,它現在將使用純 Go 編譯來建立標準函式庫中使用 cgo 的套件,而不是使用預先散發的套件封存(如 上述所述,已移除預先散發的套件封存)或嘗試使用 cgo 而失敗。這使得 Go 能夠在某些極小化容器環境中以及在 macOS 上運作良好,自 Go 1.16 起,macOS 已針對基於 cgo 的套件停止使用預先散發的套件封存。

標準函式庫中使用 cgo 的套件有 netos/userplugin。在 macOS 上,netos/user 套件已經改寫成不使用 cgo:相同的程式碼現在用於 cgo 和非 cgo 編譯,以及交叉編譯。在 Windows 作業系統上,netos/user 套件從未使用過 cgo。在其他系統上,停用 cgo 的編譯將使用這些套件的純 Go 版本。

後果是,在 macOS 上,如果使用 net 套件的 Go 程式碼是使用 -buildmode=c-archive 建立的,將產生的封存連結到 C 程式碼中需要在連結 C 程式碼時傳遞 -lresolv

在 macOS 上,競爭偵測器已改寫成不使用 cgo:啟用競爭偵測器的程式可以在沒有 Xcode 的情況下建立並執行。在 Linux 及其他 Unix 系統和 Windows 作業系統上,使用競爭偵測器需要主機 C 工具鏈。

涵蓋範圍

Go 1.20 支援為程式(應用程式和整合測試)收集程式碼涵蓋率設定檔,而不僅僅是單元測試。

要為程式收集涵蓋率資料,請使用 go build-cover 旗標來建立程式,然後使用環境變數 GOCOVERDIR 執行產生的二進位檔,並將此變數設定為涵蓋率設定檔的輸出目錄。請參閱 「整合測試的涵蓋範圍」登陸頁,以進一步了解如何開始使用。有關設計和實作的詳細資訊,請參閱 提案

驗證工具

改進巢狀函式中迴圈變數擷取的偵測

vet 工具現在會回報在子測試函式本體中呼叫 T.Parallel() 之後的迴圈變數之指標。這些指標可能會從不同的反覆運算(通常會導致跳過測試案例)或因為未同步的同時存取而產生無效的狀態中觀察變數值。

這個工具也會在更多地方偵測到指標錯誤。以前它只會考量迴圈本體的最後一個陳述,但現在它會遞迴檢查 if、switch 和 select 陳述中的最後一個陳述。

對不正確時間格式的新診斷

vet 工具現在會回報使用 Time.Formattime.Parse 採用 2006-02-01(yyyy-dd-mm)時間格式。此格式並未出現在常見的日期標準中,但常在嘗試使用 ISO 8601 日期格式(yyyy-mm-dd)時誤用。

執行時期

重新整理了垃圾收集器的部分內部資料結構,使其同時更省空間且更省 CPU。此變更縮減了記憶體開銷,並將整體 CPU 效能提升了最高 2%。

在某些情況下,垃圾收集器在協助執行常式的表現變得比較少變化。

Go 1.20 新增一個 runtime/coverage 套件,其中包含 API,可從不透過 os.Exit() 終止的長時間執行或伺服器程式中,在執行時期寫入程式碼覆蓋率資料。

編譯器

Go 1.20 新增對輪廓引導最佳化 (PGO) 的預覽支援。PGO 讓工具組能根據執行時期輪廓資訊執行特定於應用程式和工作負載的最佳化。目前,編譯器支援 pprof CPU 輪廓,可透過一般方式(例如 runtime/pprofnet/http/pprof 套件)收集。如前述 上方 所提,若要啟用 PGO,請透過傳遞 pprof 輪廓檔案的 路徑至 -pgo 旗標來執行 go build。Go 1.20 使用 PGO 在熱門呼叫網站積極內嵌函式。針對一群代表性的 Go 程式進行的基準測試顯示,啟用輪廓引導內嵌最佳化,可將效能提升約 3–4%。詳情文件請參閱 PGO 使用者指南。我們計畫在日後的版本中新增其他輪廓引導最佳化。請注意,輪廓引導最佳化為預覽版,因此請在使用時格外小心。

Go 1.20 編譯器已更新其前端,採用新的方式處理編譯器的內部資料,修復了許多泛型型別問題,並開放了泛型函式和方法中的型別宣告。

現在,編譯器將 拒絕匿名介面迴圈,並預設以編譯器錯誤回應。這類迴圈源自於 嵌入式介面 的棘手使用,且始終存在不易察覺的正確性問題,不過我們沒有證據顯示此類迴圈實際上會用於實務。假設沒有使用者回報受到此變更的影響,我們計畫在 Go 1.22 中更新語言規格,正式禁止此類迴圈,以便工具作者也可以停止支援。

Go 1.18 和 1.19 的編譯速度出現倒退,主要是因為新增對泛型的支援及後續工作。Go 1.20 將編譯速度提升了最高 10%,讓它和 Go 1.17 一樣快。與 Go 1.19 比較起來,產生的程式碼效能通常也會略微提升。

連結器

在 Linux 上,連結器現在會在連結時,選擇 glibcmusl 的動態詮釋器。

在 Windows 上,Go 連結器現在支援以 LLVM 為基礎的 C 工具鏈。

Go 1.20 會使用 go:type: 前綴,來產生編譯器產生的符號,而不會使用 go.type.。這樣可以避免名稱以 go. 開頭的使用者套件產生混淆。debug/gosym 套件會了解這個二進位檔的新命名慣例,因為它是用 Go 1.20 或更新版本所建置。

起始程式

在從原始程式碼建置 Go 版本時,如果 GOROOT_BOOTSTRAP 沒有設定,之前版本的 Go 會在 $HOME/go1.4 目錄中搜尋 Go 1.4 或更新版本的起始工具鏈(%HOMEDRIVE%%HOMEPATH%\go1.4 在 Windows 上)。在預期 Go 1.20 的起始程式需要 Go 1.17 之前,Go 1.18 和 Go 1.19 會先搜尋 $HOME/go1.17$HOME/sdk/go1.17,然後最後再使用 $HOME/go1.4。Go 1.20 確實需要 Go 1.17 版本才能進行起始設定,但我們了解應該採用起始工具鏈的最新小版本,因此需要 Go 1.17.13。在使用 $HOME/go1.4 之前(支援硬編碼路徑 $HOME/go1.4 但已安裝較新 Go 工具鏈的系統),Go 1.20 會先搜尋 $HOME/go1.17.13 $HOME/sdk/go1.17.13。在未來,我們計畫每年將起始工具鏈往前推進一次,特別是,我們預計 Go 1.22 會需要 Go 1.20 的最終小版本才能進行起始設定。

標準程式庫

新的 crypto/ecdh 套件

Go 1.20 新增一個 crypto/ecdh 套件,來明確支援 NIST 曲線和 Curve25519 的橢圓曲線 Diffie-Hellman 金鑰交換。

程式應該針對 ECDH 使用 crypto/ecdh,而非 crypto/elliptic 中的較低階層功能,以及第三方模組用於更進階的用例。

封裝多重錯誤

Go 1.20 擴充了錯誤封裝的支援,允許錯誤封裝多個其他錯誤。

錯誤 e 可以提供傳回 []errorUnwrap 方法,來封裝多個錯誤。

errors.Iserrors.As 函式已更新以檢查多重包覆的錯誤。

fmt.Errorf 函式現在支援多個 %w 格式動詞,這將導致函式傳回包裹所有這些錯誤運算元的錯誤。

新函式 errors.Join 傳回包裹錯誤清單的錯誤。

HTTP ResponseController

新的 "net/http".ResponseController 型別提供對 "net/http".ResponseWriter 介面未處理的延伸單次要求功能的存取。

以前我們已定義 ResponseWriter 可執行的可選介面(例如 Flusher)來新增新的單次要求功能。這些介面無法發現且使用起來很笨拙。

ResponseController 型別提供了更清楚、更易於發現的方式來新增每個處理控制項。在 Go 1.20 中新增的兩個此類控制項為 SetReadDeadlineSetWriteDeadline,它們可設定每個要求的讀取和寫入期限。例如

func RequestHandler(w ResponseWriter, r *Request) {
  rc := http.NewResponseController(w)
  rc.SetWriteDeadline(time.Time{}) // disable Server.WriteTimeout when sending a large response
  io.Copy(w, bigData)
}

新的 ReverseProxy 改寫掛鉤

httputil.ReverseProxy 轉發 proxy 包含一個新的 Rewrite 掛鉤函式,取代以前的 Director 掛鉤。

Rewrite 掛鉤會接受 ProxyRequest 參數,其中包括 proxy 接收到的進程請求和它將傳送的出站請求。這允許 Rewrite 掛鉤避免惡意進程請求會導致掛鉤新增的標頭在轉發之前被移除的特定案例(與只針對出站請求執行的 Director 掛鉤不同)。請參閱 議題 #50580

ProxyRequest.SetURL 方法會將出站請求路由到所提供的目的地,並取代 NewSingleHostReverseProxy 函式。與 NewSingleHostReverseProxy 不同,SetURL 也會設定出站請求的 Host 標頭。

ProxyRequest.SetXForwarded 方法會設定出站請求的 X-Forwarded-ForX-Forwarded-HostX-Forwarded-Proto 標頭。使用 Rewrite 時,預設不會新增這些標頭。

使用這些功能的 Rewrite 掛鉤範例如下

proxyHandler := &httputil.ReverseProxy{
  Rewrite: func(r *httputil.ProxyRequest) {
    r.SetURL(outboundURL) // Forward request to outboundURL.
    r.SetXForwarded()     // Set X-Forwarded-* headers.
    r.Out.Header.Set("X-Additional-Header", "header set by the proxy")
  },
}

當進程請求沒有 User-Agent 標頭時,ReverseProxy 不再會將 User-Agent 標頭新增到轉發的請求中。

函式庫的次要變更

一如往常,我們會基於 Go 1 的 相容性承諾 對函式庫進行各種次要變更和更新。這裡沒有列舉的各種效能改進也已更新。

archive/tar

當設定 GODEBUG=tarinsecurepath=0 環境變數時,Reader.Next 方法現在會針對檔名為絕對路徑、指向目前目錄以外位置、包含無效字元,或(在 Windows 上)是保留名稱(例如 NUL)的項目,傳回錯誤 ErrInsecurePath。未來版本的 Go 可能會預設停用不安全的路徑。

archive/zip

當設定 GODEBUG=zipinsecurepath=0 環境變數時,NewReader 現在會在開啟包含任何檔名為絕對路徑、指向目前目錄以外位置、包含無效字元,或(在 Windows 上)是保留名稱(例如 NUL)的檔案時,傳回錯誤 ErrInsecurePath。未來版本的 Go 可能會預設停用不安全的路徑。

來自於包含檔案資料的目錄檔案的讀取操作現在會傳回錯誤。zip 規格不允許目錄檔案包含檔案資料,因此此變更僅會影響從無效的檔案中讀取。

bytes

新的 CutPrefixCutSuffix 函式就像 TrimPrefixTrimSuffix,但也會回報字串是否已裁剪。

新的 Clone 函式配置位元組切片的拷貝。

context

新的 WithCancelCause 函式提供一個使用指定錯誤取消 context 的方式。可以透過呼叫新的 Cause 函式來擷取該錯誤。

crypto/ecdsa

使用支援的曲線時,現在所有的作業都以恆定時間實作。這導致 CPU 使用時間增加 5% 到 30%,主要影響 P-384 和 P-521。

新的 PrivateKey.ECDH 方法將 ecdsa.PrivateKey 轉換為 ecdh.PrivateKey

crypto/ed25519

PrivateKey.Sign 方法和 VerifyWithOptions 函式現在支援使用 Ed25519ph 簽署經先行雜湊的訊息,透過傳回 crypto.SHA512Options.HashFunc 指示。它們現在也支援透過設定新的 Options.Context 欄位所指示的 Ed25519ctx 和 Ed25519ph 與 context。

crypto/rsa

新的欄位 OAEPOptions.MGFHash 允許針對 OAEP 解密另外設定 MGF1 雜湊。

crypto/rsa 現在使用新的、更安全的常量時間後端。這導致解密運算的 CPU 執行時間增加約 15%(amd64 上的 RSA-2048)至 45%(arm64 上的 RSA-4096),且在 32 位元架構上會更長。加密運算的執行速度約為先前版本的 20 倍(但仍比解密快 5 到 10 倍)。預計效能會在後續版本提升。程式不得修改或手動產生 PrecomputedValues 的欄位。

crypto/subtle

新的函式 XORBytes 將兩個位元組切片進行 XOR。

crypto/tls

已剖析的憑證現在會在所有正在使用該憑證的客戶端間共用。在與伺服器或一組共用憑證鏈任何部分的伺服器建立多個同時連線的程式中,這能顯著節省記憶體。

如果握手失敗是因為憑證驗證失敗,TLS 客戶端和伺服器現在會傳回包含呈現的憑證的新型態錯誤 CertificateVerificationError

crypto/x509

ParsePKCS8PrivateKeyMarshalPKCS8PrivateKey 現在支援類型為 *crypto/ecdh.PrivateKey 的金鑰。 ParsePKIXPublicKeyMarshalPKIXPublicKey 現在支援類型為 *crypto/ecdh.PublicKey 的金鑰。剖析 NIST 曲線金鑰仍然傳回類型為 *ecdsa.PublicKey*ecdsa.PrivateKey 的值。使用它們新的 ECDH 方法轉換為類型 crypto/ecdh

新的 SetFallbackRoots 函式允許程式定義一組替代性根憑證,以防作業系統驗證器或標準平台根繫在執行時無法使用。它最常與 golang.org/x/crypto/x509roots/fallback 這個新套件一起使用,此套件會提供最新的根繫。

debug/elf

嘗試使用 Section.DataSection.Open 傳回的讀取器從 SHT_NOBITS 區段讀取資料現在會傳回錯誤。

新增 R_LARCH_* 常數供與 LoongArch 系統搭配使用。

新增 R_PPC64_* 常數供與 PPC64 ELFv2 重定位搭配使用。

已修正 R_PPC64_SECTOFF_LO_DS 的常数値,從 61 更正為 62。

debug/gosym

由於 Go 符號命名慣例 變更,處理 Go 二進位檔的工具應使用 Go 1.20 的 debug/gosym 套件透明處理舊的和新的二進位檔。

debug/pe

IMAGE_FILE_MACHINE_RISCV* 常數現新增,可搭配 RISC-V 系統使用。

encoding/binary

ReadVarintReadUvarint 函數現在會在讀取部分值後傳回 io.ErrUnexpectedEOF,而非 io.EOF

encoding/xml

新的 Encoder.Close 方法可於編碼完成後檢查未關閉的元素。

解碼器現在會拒絕包含多個冒號的元素和屬性名稱,例如 <a:b:c>,以及解析為空字串的名稱空間,例如 xmlns:a=""

解碼器現在會拒絕在開啟與關閉標籤中使用不同名稱空間前置詞的元素,即使這些前置詞表示相同的名稱空間。

errors

新的 Join 函數會傳回包裝錯誤清單的錯誤。

fmt

Errorf 函數支援以 %w 格式動詞出現多次,傳回錯誤並解開為所有 %w 引數的清單。

新的 FormatString 函數會復原對應至 State 的格式化指令,這在 Formatter 實作中相當實用。

go/ast

新的 RangeStmt.Range 欄位記錄範圍語句中 range 關鍵字的位置。

新的 File.FileStartFile.FileEnd 欄位記錄整個來源檔案的起始和結束位置。

go/token

新的 FileSet.RemoveFile 方法可從 FileSet 中移除檔案。長時間執行的程式可使用這項方法釋放已不再需要的檔案所佔用的記憶體。

go/types

新的 Satisfies 函數會回報型別是否符合約束。這項變更符合 新的語言語意,區別了符合約束和實作介面。

html/template

Go 1.20.3 及後續版本 禁止在 ECMAScript 6 範本文字中執行操作。此行為可藉由設定 GODEBUG=jstmpllitinterp=1 還原。

io

新的 OffsetWriter 封裝基礎 WriterAt 並提供 SeekWriteWriteAt 方法,其有效檔案偏移位置調整為固定值。

io/fs

新錯誤 SkipAll 會立即終止 WalkDir,但成功終止。

math/big

math/big 套件的廣泛範圍和依賴輸入的時機,使其不適合執行密碼編譯。標準函式庫的密碼編譯套件不再呼叫攻擊者控制輸入的非 trivial Int 方法。未來,math/big 中的 bug 是否會被視為安全性漏洞,將取決於其對標準函式庫更廣泛的影響。

math/rand

math/rand 套件現在會自動使用隨機值更新全域亂數產生器 (由頂層函式使用,例如 Float64Int),而頂層 Seed 函式已棄用。需要可複製亂數序列的程式最好分配自己的亂數來源,使用 rand.New(rand.NewSource(種子))

需要早先一致全域更新行為的程式可在其環境中設定 GODEBUG=randautoseed=0

頂層 Read 函式已棄用。在幾乎所有情況下,crypto/rand.Read 更為合適。

mime

ParseMediaType 函式現在允許多個參數名稱,只要名稱的值相同即可。

mime/multipart

現在,Reader 類型的函式會包裝基礎 io.Reader 傳回的錯誤。

在 Go 1.19.8 及更新版本中,此套件設定上限處理的 MIME 資料大小,以防範惡意輸入。Reader.NextPartReader.NextRawPart 將一個部分的標頭數量限制為 10000,而 Reader.ReadForm 將所有 FileHeaders 中的標頭總數限制為 10000。這些限制可以使用 GODEBUG=multipartmaxheaders 設定進行調整。Reader.ReadForm 進一步將一個表單中的部分數量限制為 1000。此限制可以使用 GODEBUG=multipartmaxparts 設定進行調整。

net

LookupCNAME 現在都會持續傳回 CNAME 記錄內容(如果存在的話)。之前在 Unix 系統和使用純粹 Go 解析時,LookupCNAME 會在 CNAME 記錄所指的名稱沒有 AAAAACNAME 記錄時傳回錯誤。這次變更有將 LookupCNAME 修改為比照 Windows 上前的行為,讓 LookupCNAME 存在任何 CNAME 時都會成功執行。

Interface.Flags 現在已包含新的旗標 FlagRunning,用於指出操作上有活動的介面。管理上已組態,但未啟動的介面(例如未連接網路線)會設定 FlagUp,但不會設定 FlagRunning

新的 Dialer.ControlContext 欄位包含一個回呼函數,其類似於現有的 Dialer.Control 掛鉤,且額外接受通話內容作為參數。在 ControlContext 不為 nil 的時候,系統會忽略 Control

Go DNS 解析器會辨識 trust-ad 解析器選項。resolv.conf 中設定 options trust-ad 時,Go 解析器會在 DNS 查詢中設定 AD 位元。解析器不會在回應中使用 AD 位元。

DNS 解析會偵測 /etc/nsswitch.conf 的變更,並在檔案變更時重新載入該檔案。檢查次數每 5 秒最多一次,匹配之前對 /etc/hosts/etc/resolv.conf 的處理方式。

net/http

ResponseWriter.WriteHeader 函數現在支援傳送 1xx 狀態碼。

新的 Server.DisableGeneralOptionsHandler 組態設定可用於停用預設的 OPTIONS * 處理函式。

Transport 從代理伺服器收到 CONNECT 請求的 HTTP 回應時,就會呼叫新的 Transport.OnProxyConnectResponse 掛鉤。

HTTP 伺服器現在會接受包含主體的 HEAD 請求,而不是將其拒絕為無效請求。

net/http 函數傳回的 HTTP/2 串流錯誤可以使用 errors.As 轉換為 golang.org/x/net/http2.StreamError

cookie 名稱的前導和尾隨空白會被移除,而不是拒絕為無效名稱。例如,cookie 設定 “name =value” 現在會被接受為設定 cookie “name”。

Cookie 的 Expires 欄位為空時,現在會視為有效。Cookie.Valid 僅在設定為 Expires 時會檢查該欄位。

net/netip

新的 IPv6LinkLocalAllRoutersIPv6Loopback 函式是 net.IPv6loopbacknet.IPv6linklocalallroutersnet/netip 中的對應函式。

作業系統

在 Windows 上,名稱 NUL 不再是 MkdirStat 中的特殊情況。

在 Windows 上,如果檔案為目錄,File.Stat 現在會使用檔案控制代碼來擷取屬性。先前它會使用傳遞給 Open 的路徑,如果檔案已被移動或取代,此路徑可能不再是檔案控制代碼代表的檔案。這樣的變更會修改 Open 在沒有 FILE_SHARE_DELETE 存取權的情況下開啟目錄,其行為與一般檔案一致。

在 Windows 上,File.Seek 現在支援搜尋到目錄的開頭。

作業系統/執行

新的 Cmd 欄位 CancelWaitDelay 會指定 Cmd 在關閉其相關的 Context 或處理程序於子處理程序仍持有 I/O 管道的情況下結束時之行為。

路徑/檔案路徑

新的錯誤 SkipAll 會立即終止 Walk,但執行成功。

新的 IsLocal 函式會回報路徑是否在語彙上與目錄有關。例如,如果 IsLocal(p)true,則 Open(p) 會參照語彙上位於目前目錄根子樹之下的檔案。

反射

新的 Value.ComparableValue.Equal 方法可以用於比較兩個 Value 是否相等。Comparable 會回報 Equal 是否為針對給定 Value 接收器有效的運算。此外,Equal 會回報兩個 Value 是否相等。

新的 Value.Grow 方法會延伸分割片以確保有空間可以再放進 n 個元素。

新的 Value.SetZero 方法會設定值為其類型所指定的零值。

Go 1.18 推出了 Value.SetIterKeyValue.SetIterValue 方法。這是優化項目:v.SetIterKey(it) 會被視為等於 v.Set(it.Key())。執行錯誤地省略了未外傳欄位的檢查,而該檢查存在於未最佳化的表單中。Go 1.20 修正了這些方法,以加入未外傳欄位的檢查。

正規表示式

Go 1.19.2 和 Go 1.18.7 包含了常規表達式解析器的安全性修復,讓它能拒絕可能消耗過多記憶體的非常巨大的表達式。由於 Go 補丁版本不會引入新的 API,因此在這種情況下,解析器會回傳 syntax.ErrInternalError。Go 1.20 新增一個更明確的錯誤 syntax.ErrLarge,解析器現在回傳這個錯誤。

runtime/cgo

Go 1.20 新增 Incomplete 標記類型。由 cgo 生成的程式碼會使用 cgo.Incomplete 來標記不完整的 C 類型。

runtime/metrics

Go 1.20 新增 支援的指標,包括目前 GOMAXPROCS 設定 (/sched/gomaxprocs:threads)、執行的 cgo 呼叫數量 (/cgo/go-to-c-calls:calls)、總體 mutex 阻塞時間 (/sync/mutex/wait/total:seconds),以及垃圾收集所花費時間的各種測量值。

基於時間的直方圖指標現在較不精確,但佔用的記憶體大幅減少。

runtime/pprof

目前 Mutex 輪廓樣本經過預先調整,修復了在執行過程中抽樣速率改變時,舊的 mutex 輪廓樣本會調整不正確的問題。

在 Windows 上收集的輪廓現在包含記憶體對應資訊,這修復了與位置無關二進位檔的符號化問題。

runtime/trace

垃圾收集器的背景掃描程式現在較不頻繁地讓出,導致執行跡象中有更少無關的事件。

strings

新的 CutPrefixCutSuffix 函式類似於 TrimPrefixTrimSuffix,但也會回報字串是否有被裁切。

sync

新的 Map 方法 SwapCompareAndSwapCompareAndDelete 允許現有的映射條目以原子方式更新。

syscall

在 FreeBSD 上,FreeBSD 11 和更早版本所需的相容性墊片已被移除。

在 Linux 上,定義了其他 CLONE_* 常數,供與 SysProcAttr.Cloneflags 欄位一起使用。

在 Linux 上,新的 SysProcAttr.CgroupFDSysProcAttr.UseCgroupFD 欄位提供了一種將子行程放入特定 cgroup 的方法。

testing

新的方法 B.Elapsed 回報基準測試目前的經過時間,這可能有助於計算要使用 ReportMetric 回報的速率。

從傳遞給 T.Cleanup 的函式呼叫 T.Run 沒有明確定義,現在會引發恐慌。

time

新的時間配置常數 DateTimeDateOnlyTimeOnly 會為公開的 Go 原始碼調查中使用的三個最常見配置字串提供名稱。

新的 Time.Compare 方法會比較兩個時間。

Parse 現在會忽略其輸入中的奈秒以下精度,而不是回報這些數字為錯誤。

Time.MarshalJSON 方法現在對於遵守 RFC 3339 更加嚴格。

unicode/utf16

新的 AppendRune 函式會將給定符文的 UTF-16 編碼加入 uint16 切片,類似於 utf8.AppendRune