Go 1.13 發行說明

Go 1.13 簡介

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

從 Go 1.13 開始,go 命令預設使用 Go 模組映象和 Google 執行的 Go 校驗和資料庫下載和認證模組。有關這些服務的隱私資訊,請參閱 https://proxy.golang.org/privacy,有關配置詳細資訊,包括如何停用這些伺服器或使用不同的伺服器,請參閱 go 命令文件。如果您依賴非公共模組,請參閱 配置環境的文件

語言變化

根據 數字字面量提案,Go 1.13 支援一套更統一和現代化的數字字面量字首。

  • 二進位制整數文字:字首 0b0B 表示二進位制整數文字,例如 0b1011
  • 八進位制整數文字:字首 0o0O 表示八進位制整數文字,例如 0o660。現有由前導 0 後跟八進位制數字表示的八進位制表示法仍然有效。
  • 十六進位制浮點文字:現在可以使用字首 0x0X 以十六進位制格式表示浮點數的尾數,例如 0x1.0p-1021。十六進位制浮點數必須始終具有指數,以字母 pP 後跟十進位制指數表示。指數將尾數按 2 的指數冪縮放。
  • 虛數字面量:虛數字尾 i 現在可以與任何(二進位制、十進位制、十六進位制)整數或浮點數字面量一起使用。
  • 數字分隔符:任何數字字面量的數字現在可以使用下劃線進行分隔(分組),例如 1_000_0000b_1010_01103.1415_9265。下劃線可以出現在任意兩個數字之間或字面量字首和第一個數字之間。

根據 帶符號移位計數提案,Go 1.13 移除了 移位計數 必須為無符號的限制。此更改消除了許多人工 uint 轉換的需要,這些轉換僅是為了滿足 <<>> 運算子的此(現已刪除的)限制而引入的。

這些語言更改是透過對編譯器以及對庫包 go/scannertext/scanner(數字字面量)以及 go/types(有符號移位計數)的相應內部更改來實現的。

如果您的程式碼使用模組並且您的 go.mod 檔案指定了語言版本,請確保將其設定為至少 1.13 以訪問這些語言更改。您可以透過直接編輯 go.mod 檔案或執行 go mod edit -go=1.13 來實現。

移植

Go 1.13 是最後一個支援 Native Client (NaCl) 的版本。

對於 GOARCH=wasm,新的環境變數 GOWASM 接受一個以逗號分隔的實驗性功能列表,二進位制檔案將使用這些功能進行編譯。有效值在此處有文件說明

AIX

PPC64 上的 AIX (aix/ppc64) 現在支援 cgo、外部連結以及 c-archivepie 構建模式。

安卓

Go 程式現在與 Android 10 相容。

Darwin

如 Go 1.12 發行說明中宣佈的,Go 1.13 現在需要 macOS 10.11 El Capitan 或更高版本;對先前版本的支援已停止。

FreeBSD

如 Go 1.12 發行說明中宣佈的,Go 1.13 現在需要 FreeBSD 11.2 或更高版本;對先前版本的支援已停止。FreeBSD 12.0 或更高版本需要一個設定了 COMPAT_FREEBSD11 選項的核心(這是預設設定)。

Illumos

Go 現在支援帶有 GOOS=illumos 的 Illumos。illumos 構建標籤暗示了 solaris 構建標籤。

Windows

內部連結的 Windows 二進位制檔案指定的 Windows 版本現在是 Windows 7 而不是 NT 4.0。這已經是 Go 的最低要求版本,但可能會影響具有向後相容模式的系統呼叫的行為。這些現在將按文件記載的方式執行。外部連結的二進位制檔案(任何使用 cgo 的程式)始終指定了更新的 Windows 版本。

工具

模組

環境變數

GO111MODULE 環境變數仍然預設為 auto,但 auto 設定現在會在當前工作目錄包含或位於包含 go.mod 檔案的目錄下方時啟用 go 命令的模組感知模式——即使當前目錄在 GOPATH/src 中。此更改簡化了 GOPATH/src 中現有程式碼的遷移以及模組感知包與非模組感知匯入者的持續維護。

新的 GOPRIVATE 環境變量表示不可公開訪問的模組路徑。它作為較低級別的 GONOPROXYGONOSUMDB 變數的預設值,這些變數提供了對哪些模組透過代理獲取以及使用校驗和資料庫進行驗證的更精細控制。

GOPROXY 環境變數 現在可以設定為以逗號分隔的代理 URL 列表或特殊令牌 direct,並且其預設值現在是 https://proxy.golang.org,direct。當將包路徑解析為其包含模組時,go 命令將依次嘗試列表中每個代理上的所有候選模組路徑。無法訪問的代理或除 404 或 410 之外的 HTTP 狀態碼將終止搜尋,而不會諮詢剩餘的代理。

新的 GOSUMDB 環境變數用於識別資料庫的名稱(可選包括公鑰和伺服器 URL),該資料庫用於查詢尚未列在主模組 go.sum 檔案中的模組的校驗和。如果 GOSUMDB 不包含明確的 URL,則透過探測 GOPROXY URL 以查詢指示支援校驗和資料庫的端點來選擇 URL,如果任何代理都不支援,則回退到直接連線到指定資料庫。如果 GOSUMDB 設定為 off,則不查詢校驗和資料庫,只驗證 go.sum 檔案中已有的校驗和。

無法訪問預設代理和校驗和資料庫的使用者(例如,由於防火牆或沙盒配置)可以透過將 GOPROXY 設定為 direct 和/或將 GOSUMDB 設定為 off 來停用它們。可以使用 go env -w 來設定這些變數的預設值,而無需考慮平臺差異。

go env -w GOPROXY=direct
go env -w GOSUMDB=off

go get

在模組感知模式下,帶有 -u 標誌的 go get 現在更新的模組集更小,與 GOPATH 模式下 go get -u 更新的包集更一致。go get -u 繼續更新命令列上指定的模組和包,但此外只更新包含由指定包所匯入的包的模組,而不是包含指定包的模組的傳遞模組需求。

特別要注意的是,go get -u(不帶額外引數)現在只更新當前目錄中包的傳遞匯入。要更新主模組傳遞匯入的所有包(包括測試依賴項),請使用 go get -u all

由於上述對 go get -u 的更改,go get 子命令不再支援 -m 標誌,該標誌會導致 go get 在載入包之前停止。-d 標誌仍然支援,並且繼續導致 go get 在下載構建指定包依賴項所需的原始碼後停止。

預設情況下,模組模式下的 go get -u 只升級非測試依賴項,與 GOPATH 模式下相同。它現在也接受 -t 標誌,該標誌(與 GOPATH 模式下相同)會使 go get 包含命令列上指定包的測試匯入的包。

在模組感知模式下,go get 子命令現在支援版本字尾 @patch@patch 字尾表示命名模組,或包含命名包的模組,應更新到與構建列表中找到的版本具有相同主版本和次版本的最高補丁版本。

如果一個不帶版本字尾的模組作為引數傳遞給 go get,並且它已經需要比最新發布版本更新的版本,它將保持在更新版本。這與模組依賴項的 -u 標誌的行為一致。這可以防止從預釋出版本意外降級。新的版本字尾 @upgrade 明確請求此行為。@latest 明確請求最新版本,無論當前版本如何。

版本驗證

從版本控制系統提取模組時,go 命令現在會對請求的版本字串執行額外的驗證。

+incompatible 版本註釋繞過了在模組引入之前存在的倉庫的語義匯入版本控制要求。go 命令現在驗證此類版本不包含顯式 go.mod 檔案。

go 命令現在驗證 偽版本 與版本控制元資料之間的對映。具體來說:

  • 版本字首必須是 vX.0.0 形式,或者派生自命名修訂的祖先上的標籤,或者派生自命名修訂本身上包含 構建元資料 的標籤。
  • 日期字串必須與修訂的 UTC 時間戳匹配。
  • 修訂的短名稱必須使用與 go 命令將生成字元數相同的字元數。(對於 git 使用的 SHA-1 雜湊,是一個 12 位的字面量。)

如果主模組中的 require 指令使用了無效的偽版本,通常可以透過將版本縮減為僅提交雜湊並重新執行 go 命令(例如 go list -m allgo mod tidy)來糾正。例如,

require github.com/docker/docker v1.14.0-0.20190319215453-e7b5f7dbe98c

可以修改為

require github.com/docker/docker e7b5f7dbe98c

目前解析為

require github.com/docker/docker v0.7.3-0.20190319215453-e7b5f7dbe98c

如果主模組的某個傳遞依賴項需要無效版本或偽版本,則可以使用主模組的 go.mod 檔案中的 replace 指令 將無效版本替換為有效版本。如果替換是提交雜湊,它將解析為上述適當的偽版本。例如,

replace github.com/docker/docker v1.14.0-0.20190319215453-e7b5f7dbe98c => github.com/docker/docker e7b5f7dbe98c

目前解析為

replace github.com/docker/docker v1.14.0-0.20190319215453-e7b5f7dbe98c => github.com/docker/docker v0.7.3-0.20190319215453-e7b5f7dbe98c

Go 命令

go env 命令現在接受一個 -w 標誌,用於設定 go 命令識別的環境變數的使用者預設值,以及一個相應的 -u 標誌,用於取消先前設定的預設值。透過 go env -w 設定的預設值儲存在 os.UserConfigDir() 中的 go/env 檔案中。

go version 命令現在接受命名可執行檔案和目錄的引數。當在可執行檔案上呼叫時,go version 會列印用於構建可執行檔案的 Go 版本。如果使用 -m 標誌,go version 會列印可執行檔案嵌入的模組版本資訊(如果可用)。當在目錄上呼叫時,go version 會列印有關目錄及其子目錄中包含的可執行檔案的資訊。

新的 go build 標誌 -trimpath 從編譯後的可執行檔案中刪除所有檔案系統路徑,以提高構建的可重現性。

如果傳遞給 go build-o 標誌引用現有目錄,go build 現在將在該目錄中為與其包引數匹配的 main 包寫入可執行檔案。

go build 標誌 -tags 現在接受一個逗號分隔的構建標籤列表,以允許在 GOFLAGS 中使用多個標籤。空格分隔的形式已棄用但仍被識別並將得到維護。

go generate 現在設定 generate 構建標籤,以便可以在構建過程中搜索指令但忽略檔案。

正如 Go 1.12 發行說明中宣佈的,不再支援僅二進位制包。構建僅二進位制包(用 //go:binary-only-package 註釋標記)現在會導致錯誤。

編譯器工具鏈

編譯器採用了新的逃逸分析實現,該實現更加精確。對於大多數 Go 程式碼來說,這將是一個改進(換句話說,更多的 Go 變數和表示式分配在堆疊而不是堆上)。然而,這種提高的精度也可能破壞以前碰巧工作的無效程式碼(例如,違反 unsafe.Pointer 安全規則 的程式碼)。如果您發現任何似乎相關的迴歸,可以使用 go build -gcflags=all=-newescape=false 重新啟用舊的逃逸分析通道。使用舊逃逸分析的選項將在未來的版本中刪除。

編譯器不再向 go_asm.h 檔案發出浮點或複雜常量。這些常量始終以不能在彙編程式碼中用作數字常量的形式發出。

彙編器

彙編器現在支援 ARM v8.1 中引入的許多原子指令。

gofmt

gofmt(以及 go fmt)現在將數字字面量字首和指數規範化為小寫字母,但保留十六進位制數字不變。這在使用新的八進位制字首(0O 變為 0o)時提高了可讀性,並且重寫一致地應用。gofmt 現在還從十進位制整數虛數字面量中刪除了不必要的前導零。(為了向後相容,以 0 開頭的整數虛數字面量被視為十進位制數,而不是八進位制數。刪除多餘的前導零可以避免潛在的混淆。)例如,0B10100XabcDEF0O6601.2E301i 在應用 gofmt 後變為 0b10100xabcDEF0o6601.2e31i

godoc 和 go doc

godoc 網路伺服器不再包含在主二進位制發行版中。要在本地執行 godoc 網路伺服器,請先手動安裝它。

go get golang.org/x/tools/cmd/godoc
godoc

go doc 命令現在總是包含輸出中的包子句,除了命令。這取代了以前使用啟發式方法,導致包子句在某些條件下被省略的行為。

執行時

超出範圍的 panic 訊息現在包含超出範圍的索引以及切片的長度(或容量)。例如,對長度為 1 的切片執行 s[3] 將 panic 並顯示“runtime error: index out of range [3] with length 1”。

此版本將大多數 defer 的使用效能提高了 30%。

執行時現在更積極地將記憶體返回給作業系統,使其可用於共租用應用程式。以前,執行時在堆大小急劇增加後可能會保留記憶體五分鐘或更長時間。現在,它將在堆縮小後立即開始返回記憶體。然而,在包括 Linux 在內的許多作業系統上,作業系統本身會惰性地回收記憶體,因此在系統處於記憶體壓力下之前,程序 RSS 不會減少。

標準庫

TLS 1.3

正如 Go 1.12 中宣佈的,Go 1.13 預設在 crypto/tls 包中啟用 TLS 1.3 支援。可以透過將值 tls13=0 新增到 GODEBUG 環境變數來停用它。此選擇退出將在 Go 1.14 中刪除。

有關重要的相容性資訊,請參閱Go 1.12 發行說明

crypto/ed25519

新的 crypto/ed25519 包實現了 Ed25519 簽名方案。此功能以前由 golang.org/x/crypto/ed25519 包提供,該包在與 Go 1.13+ 一起使用時成為 crypto/ed25519 的包裝器。

錯誤包裝

Go 1.13 包含對錯誤包裝的支援,首次在 錯誤值提案 中提出,並在相關問題上進行了討論。

錯誤 e 可以透過提供一個返回 wUnwrap 方法來包裝另一個錯誤 w。程式可以同時訪問 ew,允許 ew 提供額外上下文或重新解釋它,同時仍然允許程式根據 w 做出決策。

為了支援包裝,fmt.Errorf 現在有一個用於建立包裝錯誤的 %w 動詞,並且 errors 包中有三個新函式(errors.Unwraperrors.Iserrors.As)簡化了對包裝錯誤的解包和檢查。

有關更多資訊,請閱讀 errors 包文件,或參閱 錯誤值常見問題解答。很快也會有一篇部落格文章。

對庫的微小更改

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

bytes

新的 ToValidUTF8 函式返回給定位元組切片的副本,其中每個無效的 UTF-8 位元組序列執行都替換為給定的切片。

context

透過 WithValue 返回的上下文的格式不再依賴於 fmt,並且不會以相同的方式進行字串化。依賴精確的先前字串化的程式碼可能會受到影響。

crypto/tls

對 SSL 3.0 版本 (SSLv3) 的支援 現已棄用,並將在 Go 1.14 中刪除。請注意,SSLv3 是早於 TLS 的 加密損壞 協議。

SSLv3 總是預設停用,除了 Go 1.12 中,當時它被錯誤地在伺服器端預設啟用。現在它又預設停用了。(SSLv3 從未在客戶端支援。)

TLS 1.2 和 1.3 版本現在支援 Ed25519 證書。

crypto/x509

根據 RFC 8410,證書和證書請求現在支援 Ed25519 金鑰,並且 ParsePKCS8PrivateKeyMarshalPKCS8PrivateKeyParsePKIXPublicKey 函式也支援 Ed25519 金鑰。

系統根的搜尋路徑現在包括 /etc/ssl/cert.pem,以支援 Alpine Linux 3.7+ 中的預設位置。

database/sql

新的 NullTime 型別表示一個可能為空的 time.Time

新的 NullInt32 型別表示一個可能為空的 int32

debug/dwarf

如果 Data.Type 方法在型別圖中遇到未知 DWARF 標籤,它將不再 panic。相反,它用一個 UnsupportedType 物件表示該型別元件。

errors

新的函式 As 在給定錯誤的鏈(包裝錯誤的序列)中查詢第一個與給定目標型別匹配的錯誤,如果找到,則將目標設定為該錯誤值。

新的函式 Is 報告給定錯誤值是否與另一個錯誤鏈中的錯誤匹配。

新的函式 Unwrap 返回對給定錯誤呼叫 Unwrap 的結果(如果存在)。

fmt

列印動詞 %x%X 現在以十六進位制表示法格式化浮點數和複數,分別使用小寫和大寫。

新的列印動詞 %O 以八進位制格式化整數,發出 0o 字首。

掃描器現在接受十六進位制浮點值、數字分隔下劃線以及前導 0b0o 字首。有關詳細資訊,請參閱語言更改

Errorf 函式有一個新的動詞 %w,其運算元必須是一個錯誤。從 Errorf 返回的錯誤將有一個 Unwrap 方法,該方法返回 %w 的運算元。

go/scanner

掃描器已更新以識別新的 Go 數字字面量,特別是帶 0b/0B 字首的二進位制字面量、帶 0o/0O 字首的八進位制字面量以及帶十六進位制尾數的浮點數。虛數字尾 i 現在可以與任何數字字面量一起使用,下劃線可以作為數字分隔符用於分組。有關詳細資訊,請參閱語言更改

go/types

型別檢查器已更新,以遵循整數移位的新規則。有關詳細資訊,請參閱語言更改

html/template

當使用 <script> 標籤並將“module”設定為型別屬性時,程式碼現在將被解釋為 JavaScript 模組指令碼

log

新的 Writer 函式返回標準日誌記錄器的輸出目標。

math/big

新的 Rat.SetUint64 方法將 Rat 設定為 uint64 值。

對於 Float.Parse,如果基數為 0,則數字之間可以使用下劃線以提高可讀性。有關詳細資訊,請參閱語言更改

對於 Int.SetString,如果基數為 0,則數字之間可以使用下劃線以提高可讀性。有關詳細資訊,請參閱語言更改

Rat.SetString 現在接受非十進位制浮點表示。

math/bits

AddSubMulRotateLeftReverseBytes 的執行時間現在保證與輸入無關。

net

在 Unix 系統上,如果 resolv.conf 中設定了 use-vc,則使用 TCP 進行 DNS 解析。

新欄位 ListenConfig.KeepAlive 指定監聽器接受的網路連線的 keep-alive 週期。如果此欄位為 0(預設),將啟用 TCP keep-alive。要停用它們,請將其設定為負值。

請注意,由於 keep-alive 超時而關閉的連線上的 I/O 返回的錯誤將具有一個 Timeout 方法,該方法在被呼叫時返回 true。這使得 keep-alive 錯誤難以與由於 SetDeadline 方法和類似方法設定的截止日期未達到而返回的錯誤區分開來。使用截止日期並透過 Timeout 方法或 os.IsTimeout 檢查截止日期的程式碼可能希望停用 keep-alive,或者使用 errors.Is(syscall.ETIMEDOUT)(在 Unix 系統上),該方法對於 keep-alive 超時返回 true,對於截止日期超時返回 false。

net/http

新欄位 Transport.WriteBufferSizeTransport.ReadBufferSize 允許指定 Transport 的寫入和讀取緩衝區大小。如果任一欄位為零,則使用預設大小 4KB。

新欄位 Transport.ForceAttemptHTTP2 控制在提供非零 DialDialTLSDialContext 函式或 TLSClientConfig 時是否啟用 HTTP/2。

Transport.MaxConnsPerHost 現在在 HTTP/2 下正常工作。

TimeoutHandlerResponseWriter 現在實現了 Pusher 介面。

已新增狀態碼 103 "Early Hints"

Transport 現在使用 Request.Bodyio.ReaderFrom 實現(如果可用),以最佳化寫入主體。

在遇到不支援的傳輸編碼時,http.Server 現在返回“501 Unimplemented”狀態,這是 HTTP 規範 RFC 7230 第 3.3.1 節 所強制要求的。

新的 Server 欄位 BaseContextConnContext 允許更精細地控制提供給請求和連線的 Context 值。

http.DetectContentType 現在正確檢測 RAR 簽名,並且現在還可以檢測 RAR v5 簽名。

新的 Header 方法 Clone 返回接收器的副本。

添加了一個新函式 NewRequestWithContext,它接受一個 Context 來控制建立的傳出 Request 的整個生命週期,適用於與 Client.DoTransport.RoundTrip 一起使用。

當伺服器使用 "408 Request Timeout" 響應優雅地關閉空閒連線時,Transport 不再記錄錯誤。

os

新的 UserConfigDir 函式返回用於使用者特定配置資料的預設目錄。

如果一個 File 使用 O_APPEND 標誌開啟,它的 WriteAt 方法將總是返回錯誤。

os/exec

在 Windows 上,Cmd 的環境始終繼承父程序的 %SYSTEMROOT% 值,除非 Cmd.Env 欄位包含其顯式值。

reflect

新的 Value.IsZero 方法報告 Value 是否是其型別的零值。

MakeFunc 函式現在允許對返回值進行賦值轉換,而不是要求精確的型別匹配。當返回的型別是介面型別,而實際返回的值是實現該型別的具體值時,這特別有用。

runtime

Traceback、runtime.Callerruntime.Callers 現在將初始化 PKG 全域性變數的函式稱為 PKG.init,而不是 PKG.init.ializers

strconv

對於 strconv.ParseFloatstrconv.ParseIntstrconv.ParseUint,如果基數為 0,則數字之間可以使用下劃線以提高可讀性。有關詳細資訊,請參閱語言更改

strings

新的 ToValidUTF8 函式返回給定字串的副本,其中每個無效的 UTF-8 位元組序列執行都替換為給定的字串。

sync

Mutex.LockMutex.UnlockRWMutex.LockRWMutex.RUnlockOnce.Do 的快速路徑現在已在其呼叫方中內聯。對於 amd64 上的無競爭情況,這些更改使 Once.Do 速度提高一倍,Mutex/RWMutex 方法速度提高高達 10%。

大型 Pool 不再增加停止-世界暫停時間。

Pool 在每次 GC 後不再需要完全重新填充。它現在在 GC 期間保留一些物件,而不是釋放所有物件,從而減少了 Pool 重度使用者的負載峰值。

syscall

Darwin 構建中已刪除 _getdirentries64 的使用,以允許 Go 二進位制檔案上傳到 macOS App Store。

Windows 版 SysProcAttr 中引入了新的 ProcessAttributesThreadAttributes 欄位,用於在新程序建立時公開安全設定。

在 Windows 上,Chmod 零模式不再返回 EINVAL

型別為 Errno 的值可以使用 errors.Isos 包中的錯誤值(例如 ErrExist)進行測試。

syscall/js

TypedArrayOf 已被 CopyBytesToGoCopyBytesToJS 取代,用於在位元組切片和 Uint8Array 之間複製位元組。

testing

執行基準測試時,B.N 不再進行舍入。

新的方法 B.ReportMetric 允許使用者報告自定義基準指標並覆蓋內建指標。

測試標誌現在註冊在新的 Init 函式中,該函式由生成的測試 main 函式呼叫。因此,測試標誌現在只在執行測試二進位制檔案時註冊,並且在包初始化期間呼叫 flag.Parse 的包可能會導致測試失敗。

text/scanner

掃描器已更新以識別新的 Go 數字字面量,特別是帶 0b/0B 字首的二進位制字面量、帶 0o/0O 字首的八進位制字面量以及帶十六進位制尾數的浮點數。此外,新的 AllowDigitSeparators 模式允許數字字面量包含下劃線作為數字分隔符(預設情況下為向後相容性而停用)。有關詳細資訊,請參閱語言更改

text/template

新的 切片函式 返回將其第一個引數按後續引數切片的結果。

time

FormatParse 現在支援年中的天數。

新的 Duration 方法 MicrosecondsMilliseconds 返回持續時間作為其各自命名單位的整數計數。

unicode

unicode 包和整個系統中的相關支援已從 Unicode 10.0 升級到 Unicode 11.0,該版本增加了 684 個新字元,包括七個新指令碼和 66 個新表情符號。