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 支援更統一且現代化的數字文字前綴。
- 二進位整數文字: 前綴
0b
或0B
表示二進位整數文字,例如0b1011
。 - 八進制整數文字:字首
0o
或0O
表示八進制整數文字,例如0o660
。現有的八進制表示法在八進制數字前加上0
的表示法仍然有效。 - 十六進制浮點文字:現在可以使用字首
0x
或0X
來表示浮點數的小數部分,其格式為十六進制,例如0x1.0p-1021
。十六進制浮點數必須永遠都有指數,寫成字母p
或P
,後面接著十進制的指數。指數會以 2 的指數次方來調整小數部分。 - 虛數文字:現在任何(二進制、十進制、十六進制)整數或浮點文字都可以使用虛數字尾
i
。 - 數字分隔符:現在可以使用底線分隔(群組)任何數字文字的數字,例如
1_000_000
、0b_1010_0110
或3.1415_9265
。底線可以出現在任意兩個數字或文字字首與第一個數字之間。
根據 有號移位計數提案,Go 1.13 移除了 移位計數 必須為無號的限制。此變更消除了許多人工 uint
轉換的需求,這些轉換僅為滿足此現在已移除的 <<
和 >>
算子的限制而引入。
這些程式語言變更已透過對編譯器的變更實作,並對函式庫套件 go/scanner
和 text/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-archive
和 pie
建置模式。
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
環境變數會指出未公開提供的模組路徑。它會作為下層 GONOPROXY
和 GONOSUMDB
變數的預設值,後兩者提供更細緻的控制,可使用它們來控制透過代理取得並使用雜湊值資料庫驗證的模組。
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
指令現在會驗證 偽版本 與版本控制元資料之間的對應關係。特別是
- 版本前綴必須為
vX.0.0
格式,或來自指定修訂之父層級的標籤,或來自包含 建置元資料 的標籤,且標籤本身即為指定修訂。 - 日期字串必須與該修訂的 UTC 時間戳記相符。
- 該修訂的簡稱必須使用與
go
指令會產生的相同數量的字元。(例如,git
使用的 SHA-1 哈希值為 12 位數字的前綴.)
如果 主模組 中的 require
指令使用不正確的偽版本,通常可以透過將版本修訂為僅包含提交雜湊值,然後重新執行 go
指令(例如 go
list
-m
all
或 go
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
後,0B1010
、0XabcDEF
、0O660
、1.2E3
和 01i
將變為 0b1010
、0xabcDEF
、0o660
、1.2e3
和 1i
。
godoc
和 go
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
可藉由提供會傳回w
的Unwrap
方法來包裝另一個錯誤w
。e
和w
都可用於程式,允許e
提供額外的內容至w
或重新詮釋它,同時仍允許程式依據w
做出決策。
為支援包裝,fmt.Errorf
現在有一個%w
動詞可用於建立包裝錯誤,且errors
套件中有三個新函數(errors.Unwrap
、errors.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,以及ParsePKCS8PrivateKey
、MarshalPKCS8PrivateKey
和ParsePKIXPublicKey
函數。
現已搜尋系統根目錄的途徑包括/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 進位的浮點數值、字元分隔底線,以及前導的 0b
和 0o
前綴。詳細資訊請參閱 語言變更。
函數 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
Add
、Sub
、Mul
、RotateLeft
和 ReverseBytes
的執行時間現在已保證與輸入無關。
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.WriteBufferSize
和 Transport.ReadBufferSize
允許指定 Transport
的寫入和讀取緩衝區的大小。如果任一欄位為零,則使用預設大小 4KB。
新的欄位 Transport.ForceAttemptHTTP2
控制當提供非零的 Dial
、DialTLS
或 DialContext
函數或 TLSClientConfig
時是否啟用 HTTP/2。
Transport.MaxConnsPerHost
現在可以與 HTTP/2 正常運作。
TimeoutHandler
的 ResponseWriter
現在實作 Pusher
介面。
已新增狀態碼 103
"早期提示"
。
Transport
現在使用 Request.Body
的 io.ReaderFrom
實作(如果有的話)來最佳化主體寫入。
在遇到不受支援的傳輸編碼時,http.Server
現在會傳回「501 實現中」狀態,這符合 HTTP 規格RFC 7230 的第 3.3.1 條。
新的 Server
欄位 BaseContext
和 ConnContext
可以更細微控制提供給要求和連線的 Context
值。
http.DetectContentType
現在可以正確偵測 RAR 簽章,且現在還可以偵測 RAR v5 簽章。
已新增新的函式 NewRequestWithContext
,它會接受控制已建立的外發 Request
整個生命週期的 Context
,適合用於 Client.Do
和 Transport.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.ParseFloat
、strconv.ParseInt
和 strconv.ParseUint
,如果基底為 0,則可在數字之間使用底線以增加可讀性。請參閱語言變更以取得詳細資訊。
strings
新的 ToValidUTF8
函式會傳回指定字串的副本,其中每一組無效的 UTF-8 位元組序列皆已由指定字串替換。
sync
現在 Mutex.Lock
、Mutex.Unlock
、RWMutex.Lock
、RWMutex.RUnlock
和 Once.Do
的快速路徑現在會內嵌在呼叫程式中。針對 amd64 上的非爭用案例,這些變更會讓 Once.Do
快上兩倍,而 Mutex
/RWMutex
方法則快上 10%。
大型 Pool
不再會增加中止世界暫停時間。
Pool
不再需要在每次 GC 時完全重新填滿。它現在會在 GC 期間保留一些物件,而非釋放所有物件,進而減少大量使用者的 Pool
負載尖峰。
syscall
_getdirentries64
的使用已從 Darwin 建置中移除,以允許 Go 二進位檔案上傳至 macOS App Store。
新增 SysProcAttr
中的 ProcessAttributes
和 ThreadAttributes
新欄位至 Windows,在建立新程序時公開安全性設定。
Windows 上的零 Chmod
模式不再回傳 EINVAL
。
Errno
型別的數值可以用 errors.Is
與 os
套件中的錯誤值,例如 ErrExist
,進行測試。
syscall/js
TypedArrayOf
已由 CopyBytesToGo
和 CopyBytesToJS
取代,用於在位元組切片和 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 個新表情符號。