Go 1.13 釋出說明

Go 1.13 簡介

最新的 Go 釋出版本 1.13 在 Go 1.12 六個月後推出。大部分更改項目都在工具鏈、執行時期和函式庫的實作中。一如往常,此版本維護 Go 1 相容性承諾。我們預期幾乎所有 Go 程式都會像以前一樣持續編譯和執行。

自 Go 1.13 起,go 命令會預設使用 Google 執行的 Go 模組鏡像和 Go 校驗和資料庫下載並驗證模組。請參閱 https://proxy.golang.org/privacy,以取得有關這些服務的隱私權相關資訊,並參閱 go 命令文件,以取得有關組態詳細資料的資訊,包含如何停用使用這些伺服器或使用其他伺服器。如果您依賴非公開模組,請參閱 用於組態您環境的文件

語言變更

根據 數字文字建議,Go 1.13 支援更統一且現代化的數字文字前綴。

根據 有號移位計數提案,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/ppc64) 上的 AIX 現在支援 cgo、外部連結以及 c-archivepie 建置模式。

Android

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 環境變數 現在可以設定為以逗號分隔的代理網址清單或特殊符號 direct,其 預設值 現在是 https://proxy.golang.org,direct。在將套件路徑解析到所包含的模組時,go 指令會依序嘗試清單上每個代理中的所有候選模組路徑。無法連線的代理或 HTTP 狀態碼(404 或 410 除外)將會終止搜尋,而不會查閱剩下的代理。

新的 GOSUMDB 環境變數會標示資料庫的名稱,以及(選用)公開金鑰和伺服器網址。該資料庫會針對尚未在主模組的 go.sum 檔案中列出的模組檢查雜湊值。如果 GOSUMDB 不包含明確的網址,系統會透過探查 GOPROXY 網址來選擇網址,尋找指出支援雜湊值資料庫的端點,如果沒有任何代理支援,則會改為直接連線到已命名的資料庫。如果 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 字尾表示所指定的模組,或包含所指定套件的模組,應該要更新到與建置清單中找到的版本擁有相同主要和次要版本,且 patch 等級最高的版本。

如果傳遞至 go get 的模組是沒有版本字尾的引數,且最新已發佈的版本已經比較新的版本更新,則它會維持在較新的版本。這與模組相依性對 -u 標記的行為是一致的。這會防止因先前的版本而進行意外的降級。新的版本字尾 @upgrade 會明確要求這種行為。@latest 會明確要求最新版本,不管目前的版本為何。

版本驗證

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

+incompatible 版本註解會略過 語意匯入版本控管 的要求,適用於在推出模組之前就已存在的儲存庫。go 指令現在會驗證此類版本是否不包含明示的 go.mod 檔案。

go 指令現在會驗證 偽版本 與版本控制元資料之間的對應關係。特別是

如果 主模組 中的 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

如果主模組的其中一個遞迴相依項需要不正確的版本或偽版本,可以使用 replace 指令 將不正確的版本替換為正確的版本,該指令會出現在主模組的 go.mod 檔案中。如果替換為提交雜湊值,則會如上述內容解析為適當的偽版本。例如,

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 的浮點數複數字面值會視為十進位數,而非八進制數字。移除多餘開頭零可避免潛在混淆)。舉例來說,在套用 gofmt 後,0B10100XabcDEF0O6601.2E301i 將變為 0b10100xabcDEF0o6601.2e31i

godocgo doc

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

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

go doc 指令現會在輸出中持續納入套件條款,指令例外。此變更取代之前的經驗法則,使套件條款在特定狀況下會被省略。

執行時期

超出範圍的恐慌訊息現會納入範圍外的索引和切片長度(或容量)。舉例來說,對長度為 1 的切片執行 s[3] 將會產生恐慌「執行時期錯誤:索引超出範圍 [3],長度為 1」。

此版本改善了大多數 defer 用法的效能達 30%。

執行時期現在會更積極地將記憶體還原給作業系統,使其可用於同主機應用程式。之前,執行時期可能會在堆積大小激增後保留記憶體達五分鐘以上。作業系統縮減後,記憶體現在會很快地被歸還。不過,在許多作業系統(包括 Linux)上,作業系統本身會延後進行記憶體回收,因此處理程序 RSS 只有在系統記憶體不足時才會減少。

標準函式庫

TLS 1.3

如同 Go 1.12 中宣布,Go 1.13 已預設啟用 crypto/tls 套件中的 TLS 1.3 支援。透過將 tls13=0 值新增至 GODEBUG 環境變數,可停用這項功能。選擇停用 TLS 1.3 的機制將會在 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方法來包裝另一個錯誤wew都可用於程式,允許e提供額外的內容至w或重新詮釋它,同時仍允許程式依據w做出決策。

為支援包裝,fmt.Errorf現在有一個%w動詞可用於建立包裝錯誤,且errors套件中有三個新函數(errors.Unwraperrors.Is以及errors.As)簡化了解包裝和檢查包裝錯誤。

如需更多資訊,請閱讀errors套件文件或參閱錯誤值常見問題解答。稍後也會有一篇部落格文章。

程式庫的輕微變更

一如往常,程式庫有各種輕微變更和更新,考量到Go 1相容性承諾

bytes

新的ToValidUTF8函數傳回一個給定位元組切片的副本,其中每個無效UTF-8位元組序列會由一個給定的切片取代。

context

WithValue傳回之內容的格式不再仰賴fmt,也不會以相同的方式字串化。依賴先前的確切字串化的程式碼可能會受到影響。

crypto/tls

對SSL版本3.0 (SSLv3)的支援現已不建議使用,且會在Go 1.14中移除。請注意SSLv3是先於TLS的密碼破譯協定。

在Go 1.12中,SSLv3錯誤地預設在伺服器端啟用以外,其他時間均預設停用。現在又再度預設停用。(SSLv3從未在用戶端支援。)

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

crypto/x509

Ed25519金鑰現在支援於憑證和憑證要求中,依據RFC 8410,以及ParsePKCS8PrivateKeyMarshalPKCS8PrivateKeyParsePKIXPublicKey函數。

現已搜尋系統根目錄的途徑包括/etc/ssl/cert.pem,用於支援Alpine Linux 3.7+的預設位置。

database/sql

新的NullTime類型代表一個可能為空的time.Time

新的NullInt32類型代表一個可能為空的int32

debug/dwarf

Data.Type 方法不再會在類型圖中遇到未知 DWARF 標記時發生恐慌。反之,它會使用 UnsupportedType 物件來表示類型的那個元件。

errors

新的函數 As 找出在給定錯誤的鏈中(一連串包裝過的錯誤)與給定目標類型相符的錯誤,如果是的話,就會將目標設定為該錯誤值。

新的函數 Is 報告給定錯誤值是否與另一個鏈中的錯誤相符。

新的函數 Unwrap 傳回呼叫給定錯誤上的 Unwrap 的結果(如果存在的話)。

fmt

列印動詞 %x%X 現在會分別以小寫和中文字符格式化浮點數和複數。

新的列印動詞 %O 會格式化 8 進位的整數,並加上 0o 前綴。

scanner 現在會接受 16 進位的浮點數值、字元分隔底線,以及前導的 0b0o 前綴。詳細資訊請參閱 語言變更

函數 Errorf 有新的動詞 %w,其操作數必須是錯誤。Errorf 傳回的錯誤會有一個 Unwrap 方法,傳回 %w 的操作數。

go/scanner

scanner 已更新為辨識新的 Go 數字文字,特別是帶有 0b/0B 前綴的二進位文字、帶有 0o/0O 前綴的八進位文字,以及帶有 16 進位尾數的浮點數。現在可以用任何數字文字來使用虛數字尾 i,並且可以使用底線作為字元分隔符來進行分組。詳細資訊請參閱 語言變更

go/types

類型檢查器已更新為遵循整數轉移的新規則。詳細資訊請參閱 語言變更

html/template

當使用帶有「module」類型屬性的 <script> 標籤時,現在會將程式碼解譯為 JavaScript 模組程式碼

log

新的 Writer 函數會傳回標準記錄器的輸出目的地。

math/big

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

對於 Float.Parse,如果底數為 0,則可使用底線作為字元分隔符以提高可讀性。詳細資訊請參閱 語言變更

針對 Int.SetString,如果基底為 0,則可以在位數之間使用底線以增強可讀性。詳情請參閱 語言變更

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

math/bits

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

net

在設定檔 resolv.conf 中設定 use-vc 的 Unix 系統上,將使用 TCP 進行 DNS 解析。

新的欄位 ListenConfig.KeepAlive 指定偵聽器所接受的網路連線的保持連線時間。如果欄位為 0(預設值),將啟用 TCP 保持連線。若要停用,請將其設定為負值。

請注意,在保持連線逾時關閉的連線上的 I/O 所回傳的錯誤將有一個 Timeout 方法,如果呼叫會回傳 true。這使得保持連線的錯誤難以與由 SetDeadline 方法和類似方法設定的未達預定完成時間而回傳的錯誤區分。使用預定完成時間並透過 Timeout 方法或 os.IsTimeout 檢查預定完成時間的程式碼可能需要停用保持連線,或使用 errors.Is(syscall.ETIMEDOUT)(在 Unix 系統上)對保持連線超過時間會回傳 true,對預定完成時間超過時間會回傳 false。

net/http

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

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

Transport.MaxConnsPerHost 現在可以與 HTTP/2 正常運作。

TimeoutHandlerResponseWriter 現在實作 Pusher 介面。

已新增狀態碼 103 "早期提示"

Transport 現在使用 Request.Bodyio.ReaderFrom 實作(如果有的話)來最佳化主體寫入。

在遇到不受支援的傳輸編碼時,http.Server 現在會傳回「501 實現中」狀態,這符合 HTTP 規格RFC 7230 的第 3.3.1 條

新的 Server 欄位 BaseContextConnContext 可以更細微控制提供給要求和連線的 Context 值。

http.DetectContentType 現在可以正確偵測 RAR 簽章,且現在還可以偵測 RAR v5 簽章。

新的 Header 方法 Clone 會傳回接收者的副本。

已新增新的函式 NewRequestWithContext,它會接受控制已建立的外發 Request 整個生命週期的 Context,適合用於 Client.DoTransport.RoundTrip

當伺服器使用「408 要求逾時」回應優雅地關閉閒置連線時,Transport 不再會記錄錯誤。

os

新的 UserConfigDir 函式會傳回用於使用者特定組態資料的預設目錄。

File 使用 O_APPEND 旗標開啟時,其 WriteAt 方法將始終傳回錯誤。

os/exec

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

reflect

新的 Value.IsZero 方法會報告 Value 是否為其類型的 0 值。

MakeFunc 函式現在允許在傳回值上進行指定轉換,而不必進行完全類型比對。當傳回的類型是介面類型,但實際傳回的值是實作該類型的具體值時,這非常有用。

runtime

Traceback、runtime.Caller,以及 runtime.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

_getdirentries64 的使用已從 Darwin 建置中移除,以允許 Go 二進位檔案上傳至 macOS App Store。

新增 SysProcAttr 中的 ProcessAttributesThreadAttributes 新欄位至 Windows,在建立新程序時公開安全性設定。

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

現在,格式化解析支援年分日數。

新的持續時間方法微秒毫秒傳回持續時間為各自命名單位的整數計數。

unicode

unicode套件和整個系統中相關的支援已從 Unicode 10.0 升級到Unicode 11.0,新增 684 個新字元,包括七個新腳本和 66 個新表情符號。