Go 1.14 發行說明

Go 1.14 簡介

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

go 命令中的模組支援現已準備好投入生產使用,我們鼓勵所有使用者遷移到 Go 模組進行依賴管理。如果您由於 Go 工具鏈中的問題而無法遷移,請確保已提交開放問題。(如果問題不在 Go1.15 里程碑中,請告知我們它為何阻止您遷移,以便我們進行適當的優先順序排序。)

語言變化

根據重疊介面提案,Go 1.14 現在允許嵌入具有重疊方法集的介面:來自嵌入介面的方法可能與(嵌入)介面中已存在的方法具有相同的名稱和相同的簽名。這解決了通常(但不限於)發生在菱形嵌入圖中的問題。介面中顯式宣告的方法必須像以前一樣保持唯一

移植

Darwin

Go 1.14 是最後一個在 macOS 10.11 El Capitan 上執行的版本。Go 1.15 將需要 macOS 10.12 Sierra 或更高版本。

Go 1.14 是最後一個支援 macOS 上 32 位二進位制檔案(darwin/386 埠)的 Go 版本。從 macOS 10.15 (Catalina) 開始,macOS 不再支援它們。Go 繼續支援 64 位 darwin/amd64 埠。

Go 1.14 可能是最後一個支援 iOS、iPadOS、watchOS 和 tvOS(darwin/arm 埠)上 32 位二進位制檔案的 Go 版本。Go 繼續支援 64 位 darwin/arm64 埠。

Windows

Windows 上的 Go 二進位制檔案現在已啟用 DEP(資料執行保護)

在 Windows 上,如果許可權引數中未設定位 0o200(所有者寫入許可權),則透過 os.OpenFile 使用 os.O_CREATE 標誌或透過 syscall.Open 使用 syscall.O_CREAT 標誌建立檔案現在將以只讀方式建立檔案。這使得 Windows 上的行為更像 Unix 系統上的行為。

WebAssembly

現在可以透過垃圾回收機制回收透過 js.Value 物件從 Go 引用 JavaScript 值。

js.Value 值不再可以使用 == 運算子進行比較,而必須使用它們的 Equal 方法進行比較。

js.Value 現在具有 IsUndefinedIsNullIsNaN 方法。

RISC-V

Go 1.14 包含對 Linux 上 64 位 RISC-V 的實驗性支援(GOOS=linux, GOARCH=riscv64)。請注意,效能、彙編語法穩定性以及可能的正確性仍在開發中。

FreeBSD

Go 現在支援 FreeBSD 12.0 或更高版本上的 64 位 ARM 架構(freebsd/arm64 埠)。

Native Client (NaCl)

如 Go 1.13 發行說明中宣佈的那樣,Go 1.14 放棄了對 Native Client 平臺(GOOS=nacl)的支援。

Illumos

執行時現在為 runtime.NumCPUGOMAXPROCS 的預設值遵守區域 CPU 上限(zone.cpu-cap 資源控制)。

工具

Go 命令

Vendoring(供應商化)

當主模組包含頂級 vendor 目錄且其 go.mod 檔案指定 go 1.14 或更高版本時,go 命令現在對接受該標誌的操作預設使用 -mod=vendor。該標誌的新值 -mod=mod 會使 go 命令從模組快取載入模組(就像沒有 vendor 目錄一樣)。

當設定了 -mod=vendor(顯式或預設)時,go 命令現在會驗證主模組的 vendor/modules.txt 檔案與其 go.mod 檔案是否一致。

go list -m 不再靜默省略 vendor 目錄中不提供包的傳遞依賴項。如果設定了 -mod=vendor 並且請求的資訊未在 vendor/modules.txt 中提及,它現在會顯式失敗。

標誌

go get 命令不再接受 -mod 標誌。以前,該標誌的設定要麼被忽略,要麼導致構建失敗

go.mod 檔案是隻讀且不存在頂級 vendor 目錄時,-mod=readonly 現在預設設定。

-modcacherw 是一個新標誌,指示 go 命令將模組快取中新建立的目錄保留其預設許可權,而不是將其設定為只讀。使用此標誌會使測試或其他工具更有可能意外新增未包含在模組已驗證校驗和中的檔案。但是,它允許使用 rm -rf(而不是 go clean -modcache)來刪除模組快取。

-modfile=file 是一個新標誌,指示 go 命令讀取(並可能寫入)替代的 go.mod 檔案,而不是模組根目錄中的檔案。名為 go.mod 的檔案仍必須存在才能確定模組根目錄,但不會訪問它。指定 -modfile 時,還會使用替代的 go.sum 檔案:其路徑是透過從 -modfile 標誌中截斷 .mod 副檔名並追加 .sum 派生的。

環境變數

GOINSECURE 是一個新環境變數,指示 go 命令在直接從其來源獲取某些模組時,不要求 HTTPS 連線並跳過證書驗證。與現有 GOPRIVATE 變數一樣,GOINSECURE 的值是逗號分隔的 glob 模式列表。

模組外的命令

當顯式啟用模組感知模式(透過設定 GO111MODULE=on)時,如果沒有 go.mod 檔案,大多數模組命令的功能會受到更多限制。例如,go buildgo run 和其他構建命令只能構建標準庫中的包以及命令列上指定為 .go 檔案的包。

以前,go 命令會將每個包路徑解析為模組的最新版本,但不會記錄模組路徑或版本。這導致了緩慢、不可重現的構建

go get 繼續像以前一樣工作,go mod download 和帶有顯式版本的 go list -m 也是如此。

+incompatible 版本

如果模組的最新版本包含 go.mod 檔案,除非明確請求或已要求,否則 go get 將不再升級到該模組的不相容主要版本。go list 在直接從版本控制獲取此類模組時也省略了不相容的主要版本,但如果代理報告,則可能包含它們。

go.mod 檔案維護

除了 go mod tidy 之外的 go 命令不再刪除指定主模組的其他(傳遞)依賴項已隱含的間接依賴項版本的 require 指令。

除了 go mod tidy 之外的 go 命令不再編輯 go.mod 檔案,如果更改僅是裝飾性的。

當設定了 -mod=readonly 時,go 命令將不再因缺少 go 指令或錯誤的 // indirect 註釋而失敗。

模組下載

go 命令現在在模組模式下支援 Subversion 儲存庫。

go 命令現在包含來自模組代理和其他 HTTP 伺服器的純文字錯誤訊息片段。只有當錯誤訊息是有效的 UTF-8 且僅包含圖形字元和空格時,才會顯示它。

測試

go test -v 現在會在 t.Log 輸出發生時流式傳輸,而不是在所有測試結束時。

執行時

此版本改進了 defer 的大多數用例的效能,使其與直接呼叫延遲函式相比,幾乎沒有開銷。因此,defer 現在可以在對效能敏感的程式碼中使用,而無需擔心開銷。

Goroutines 現在可以非同步搶佔。因此,不帶函式呼叫的迴圈不再可能使排程程式死鎖或顯著延遲垃圾回收。這在所有平臺(windows/armdarwin/armjs/wasmplan9/* 除外)上都受支援。

搶佔實現的一個結果是,在 Unix 系統(包括 Linux 和 macOS 系統)上,使用 Go 1.14 構建的程式將比使用早期版本構建的程式收到更多訊號。這意味著使用 syscallgolang.org/x/sys/unix 等包的程式將看到更多慢速系統呼叫失敗並出現 EINTR 錯誤。這些程式必須以某種方式處理這些錯誤,最可能是迴圈以再次嘗試系統呼叫。有關此內容的更多資訊,請參閱 Linux 系統的 man 7 signal 或其他系統的類似文件。

頁分配器效率更高,並且在 GOMAXPROCS 值較高時,鎖競爭顯著減少。這在並行且高速進行的大量分配中表現為較低的延遲和較高的吞吐量。

內部計時器(由 time.Aftertime.Ticknet.Conn.SetDeadline 等使用)效率更高,鎖競爭更少,上下文切換更少。這是一項效能改進,不應導致任何使用者可見的更改。

編譯器

此版本添加了 -d=checkptr 作為編譯時選項,用於新增檢測以動態檢查 Go 程式碼是否遵循 unsafe.Pointer 安全規則。此選項預設啟用(Windows 除外),帶有 -race-msan 標誌,並可以透過 -gcflags=all=-d=checkptr=0 停用。具體來說,-d=checkptr 檢查以下內容

  1. unsafe.Pointer 轉換為 *T 時,結果指標必須為 T 適當地對齊。
  2. 如果指標算術的結果指向 Go 堆物件,則其中一個 unsafe.Pointer 型別的運算元必須指向同一物件。

目前不建議在 Windows 上使用 -d=checkptr,因為它會在標準庫中導致誤報。

編譯器現在可以使用 -json 標誌輸出關鍵最佳化的機器可讀日誌,包括內聯、逃逸分析、邊界檢查消除和 nil 檢查消除。

詳細的逃逸分析診斷(-m=2)現在再次生效。這已從上一個版本中新的逃逸分析實現中刪除。

macOS 二進位制檔案中的所有 Go 符號現在都以一個下劃線開頭,遵循平臺約定。

此版本包含對編譯器插入覆蓋率檢測以進行模糊測試的實驗性支援。有關更多詳細資訊,請參閱問題 14565。此 API 可能會在未來版本中更改。

邊界檢查消除現在使用來自切片建立的資訊,並且可以消除型別小於 int 的索引的檢查。

標準庫

新位元組序列雜湊包

Go 1.14 包含一個新包 hash/maphash,它提供位元組序列上的雜湊函式。這些雜湊函式旨在用於實現雜湊表或其他需要將任意字串或位元組序列對映到無符號 64 位整數上的均勻分佈的資料結構。

雜湊函式是抗碰撞的,但不是加密安全的。

給定位元組序列的雜湊值在單個程序中是一致的,但在不同程序中將是不同的。

對庫的微小更改

與往常一樣,庫中有各種微小的更改和更新,這些都是在遵守 Go 1 相容性承諾的前提下進行的。

crypto/tls

已移除對 SSL 3.0 版本 (SSLv3) 的支援。請注意,SSLv3 是早於 TLS 的加密損壞協議。

TLS 1.3 不能再透過 GODEBUG 環境變數停用。使用 Config.MaxVersion 欄位配置 TLS 版本。

當透過 Config.Certificates 欄位提供多個證書鏈時,現在會自動選擇與對等方相容的第一個證書鏈。這允許例如提供 ECDSA 和 RSA 證書,並讓包自動選擇最佳證書。請注意,如果未設定 Certificate.Leaf 欄位,則此選擇的效能會很差。Config.NameToCertificate 欄位僅支援將單個證書與給定名稱關聯,現在已棄用,應將其保留為 nil。類似地,Config.BuildNameToCertificate 方法(它從葉證書構建 NameToCertificate 欄位)現在已棄用,不應呼叫。

新的 CipherSuitesInsecureCipherSuites 函式返回當前已實現的密碼套件列表。新的 CipherSuiteName 函式返回密碼套件 ID 的名稱。

新的 (*ClientHelloInfo).SupportsCertificate (*CertificateRequestInfo).SupportsCertificate 方法公開對等方是否支援某個證書。

tls 包不再支援舊版下一協議協商 (NPN) 擴充套件,現在只支援 ALPN。在以前的版本中,它兩者都支援。沒有 API 更改,應用程式應該像以前一樣執行。大多數其他客戶端和伺服器已經刪除了 NPN 支援,轉而支援標準化的 ALPN。

在 TLS 1.2 握手中,當支援時現在使用 RSA-PSS 簽名。這不會影響大多數應用程式,但不支援 RSA-PSS 簽名的自定義 Certificate.PrivateKey 實現將需要使用新的 Certificate.SupportedSignatureAlgorithms 欄位來停用它們。

如果設定了 Config.GetConfigForClient,則 Config.CertificatesCertificateRequestInfo.Version 欄位為客戶端證書回撥提供 TLS 版本。

新的 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 常量使用之前稱為 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 的密碼套件的最終名稱。

crypto/x509

Certificate.CreateCRL 現在支援 Ed25519 頒發者。

debug/dwarf

debug/dwarf 包現在支援讀取 DWARF 版本 5。

新方法 (*Data).AddSection 支援將輸入檔案中的任意新 DWARF 節新增到 DWARF Data 中。

新方法 (*Reader).ByteOrder 返回當前編譯單元的位元組序。這可以用於解釋以本機順序編碼的屬性,例如位置描述。

新方法 (*LineReader).Files 從行讀取器返回檔案名錶。這可以用於解釋 DWARF 屬性(如 AttrDeclFile)的值。

encoding/asn1

Unmarshal 現在支援 ASN.1 字串型別 BMPString,由新的 TagBMPString 常量表示。

encoding/json

Decoder 型別支援一個新方法 InputOffset,它返回當前解碼器位置的輸入流位元組偏移量。

Compact 不再轉義 U+2028U+2029 字元,這從來都不是一個文件化的功能。要進行正確的轉義,請參閱 HTMLEscape

Number 不再接受無效數字,以更緊密地遵循文件化行為。如果程式需要接受空字串等無效數字,請考慮使用 Unmarshaler 包裝該型別。

Unmarshal 現在可以支援具有實現 encoding.TextUnmarshaler 的底層字串型別的對映鍵。

go/build

Context 型別有一個新欄位 Dir,可用於設定構建的工作目錄。預設值是執行程序的當前目錄。在模組模式下,這用於查詢主模組。

go/doc

新函式 NewFromFiles*ast.File 列表計算包文件,並將示例與適當的包元素關聯。新資訊在 PackageTypeFunc 型別的新 Examples 欄位以及 Example 型別的新 Suffix 欄位中可用。

io/ioutil

TempDir 現在可以建立名稱具有可預測字首和字尾的目錄。與 TempFile 一樣,如果模式包含“*”,則隨機字串替換最後一個“*”。

log

新標誌 Lmsgprefix 可用於告知日誌函式在日誌訊息之前而不是在行開頭立即發出可選的輸出字首。

math

新函式 FMA 在浮點數中計算 x*y+z,而沒有對 x*y 計算進行中間舍入。一些架構使用專用硬體指令實現此計算,以提高效能。

math/big

GCD 方法現在允許輸入 ab 為零或負數。

math/bits

新函式 RemRem32Rem64 支援即使商溢位也能計算餘數。

mime

.js.mjs 檔案的預設型別現在是 text/javascript 而不是 application/javascript。這符合 IETF 草案,該草案將 application/javascript 視為已過時。

mime/multipart

新的 Reader 方法 NextRawPart 支援獲取下一個 MIME 部分,而無需透明地解碼 quoted-printable 資料。

net/http

新的 Header 方法 Values 可用於獲取與規範化鍵關聯的所有值。

新的 Transport 欄位 DialTLSContext 可用於指定用於為非代理 HTTPS 請求建立 TLS 連線的可選撥號函式。此新欄位可以代替 DialTLS 使用,後者現在被視為已棄用;DialTLS 將繼續工作,但新程式碼應使用 DialTLSContext,它允許傳輸在不再需要撥號時立即取消撥號。

在 Windows 上,ServeFile 現在可以正確地提供大於 2GB 的檔案。

net/http/httptest

新的 Server 欄位 EnableHTTP2 支援在測試伺服器上啟用 HTTP/2。

net/textproto

新的 MIMEHeader 方法 Values 可用於獲取與規範化鍵關聯的所有值。

net/url

當 URL 解析失敗時(例如透過 ParseParseRequestURI),結果 Error 訊息現在將引用無法解析的 URL。這提供了更清晰的結構並與其他解析錯誤保持一致。

os/signal

在 Windows 上,CTRL_CLOSE_EVENTCTRL_LOGOFF_EVENTCTRL_SHUTDOWN_EVENT 事件現在會生成 syscall.SIGTERM 訊號,類似於 Control-C 和 Control-Break 生成 syscall.SIGINT 訊號的方式。

外掛

plugin 包現在支援 freebsd/amd64

reflect

StructOf 現在支援透過設定 StructField 元素中的 PkgPath 欄位來建立具有未匯出欄位的結構型別。

runtime

runtime.Goexit 不能再被遞迴的 panic/recover 中止。

在 macOS 上,SIGPIPE 不再轉發給 Go 執行時初始化之前安裝的訊號處理程式。這是必要的,因為 macOS 將 SIGPIPE 傳送到主執行緒而不是寫入關閉管道的執行緒。

runtime/pprof

生成的配置檔案不再包含用於內聯標記的偽 PC。行內函數的符號資訊以 pprof 工具期望的格式編碼。這是對最近版本中引入的迴歸的修復。

strconv

NumError 型別現在有一個 Unwrap 方法,可用於檢索轉換失敗的原因。這支援使用 errors.Is 使用 NumError 值來檢視底層錯誤是否為 strconv.ErrRangestrconv.ErrSyntax

sync

解鎖高度爭用的 Mutex 現在會直接將 CPU 讓給下一個等待該 Mutex 的 goroutine。這顯著提高了高 CPU 計數機器上高度爭用的互斥鎖的效能。

testing

testing 包現在支援 cleanup 函式,在測試或基準測試完成後呼叫,分別透過呼叫 T.CleanupB.Cleanup

text/template

text/template 包現在在將帶括號的引數用作函式時會正確報告錯誤。這最常見地出現在錯誤情況中,例如 {{if (eq .F "a") or (eq .F "b")}}。這應該寫成 {{if or (eq .F "a") (eq .F "b")}}。錯誤情況從未按預期工作,現在將報告錯誤 can't give argument to non-function

JSEscape 現在轉義 &= 字元,以減輕其輸出在 HTML 上下文中被誤用的影響。

unicode

unicode 包和整個系統的相關支援已從 Unicode 11.0 升級到 Unicode 12.0,其中增加了 554 個新字元,包括四個新指令碼和 61 個新表情符號。