Go 1.9 釋出說明
Go 1.9 簡介
最新的 Go 版本 1.9 在 Go 1.8 釋出六個月後推出,是 Go 1.x 系列的第十個版本。語言方面有兩項更改:增加了對類型別名的支援,並定義了實現何時可以融合浮點運算。大部分更改都在工具鏈、執行時和庫的實現中。一如既往,此版本保持了 Go 1 相容性承諾。我們預計幾乎所有 Go 程式都能像以前一樣繼續編譯和執行。
此版本增加了透明的單調時間支援,並行編譯包內函式,更好地支援測試輔助函式,包含一個新的位操作包,並有一個新的併發對映型別。
語言變化
語言方面有兩項更改。
Go 現在支援類型別名,以支援在包之間移動型別時進行漸進式程式碼修復。類型別名設計文件和一篇關於重構的文章詳細介紹了這個問題。簡而言之,類型別名宣告的形式為
type T1 = T2
此宣告為 T2 所表示的型別引入了一個別名 T1——一個替代拼寫;也就是說,T1 和 T2 都表示相同的型別。
一個較小的語言更改是,語言規範現在規定了實現何時可以將浮點運算融合在一起,例如透過使用架構的“融合乘加”(FMA) 指令來計算 x*y + z,而不對中間結果 x*y 進行舍入。要強制進行中間舍入,請寫 float64(x*y) + z。
移植
此版本中沒有新增受支援的作業系統或處理器架構。
ppc64x 需要 POWER8
GOARCH=ppc64 和 GOARCH=ppc64le 現在都至少需要 POWER8 支援。在之前的版本中,只有 GOARCH=ppc64le 需要 POWER8,而大端 ppc64 架構支援舊硬體。
FreeBSD
Go 1.9 是最後一個將在 FreeBSD 9.3 上執行的版本,FreeBSD 9.3 已不再受 FreeBSD 支援。Go 1.10 將需要 FreeBSD 10.3+。
OpenBSD 6.0
Go 1.9 現在為 cgo 二進位制檔案啟用 PT_TLS 生成,因此需要 OpenBSD 6.0 或更新版本。Go 1.9 不再支援 OpenBSD 5.9。
已知問題
FreeBSD 上存在一些已知但原因不明的不穩定性。在極少數情況下,這可能導致程式崩潰。請參閱問題 15658。歡迎提供任何幫助來解決這個 FreeBSD 特有問題。
Go 在 Go 1.9 開發週期中停止執行 NetBSD 構建器,原因是 NetBSD 核心崩潰,包括 NetBSD 7.1。在 Go 1.9 釋出時,NetBSD 7.1.1 正在釋出一個修復程式。然而,目前我們沒有 NetBSD 構建器透過我們的測試套件。歡迎提供任何幫助來調查各種 NetBSD 問題。
工具
並行編譯
Go 編譯器現在支援並行編譯包的函式,利用多個核心。這補充了 go 命令現有的對單獨包的並行編譯支援。並行編譯預設啟用,但可以透過將環境變數 GO19CONCURRENTCOMPILATION 設定為 0 來停用。
./... 的供應商匹配
根據大眾需求,./... 在接受包名稱的工具(例如 go test)中不再匹配 vendor 目錄中的包。要匹配供應商目錄,請寫 ./vendor/...。
已移動的 GOROOT
go 工具現在將使用其被呼叫的路徑來嘗試定位 Go 安裝樹的根。這意味著如果整個 Go 安裝被移動到新位置,go 工具應該繼續正常工作。這可以透過在環境中設定 GOROOT 來覆蓋,這隻應在異常情況下進行。請注意,這不會影響 runtime.GOROOT 函式的結果,該函式將繼續報告原始安裝位置;這可能會在後續版本中修復。
編譯器工具鏈
複數除法現在與 C99 相容。gccgo 一直如此,現在 gc 工具鏈中也已修復。
連結器現在將在 Windows 上為 cgo 可執行檔案生成 DWARF 資訊。
如果提供了 -N -l 標誌,編譯器現在會在生成的 DWARF 中包含詞法作用域,允許偵錯程式隱藏不在作用域內的變數。.debug_info 部分現在是 DWARF 版本 4。
GOARM 和 GO386 的值現在會影響編譯包的構建 ID,如 go 工具的依賴快取所使用。
彙編器
四運算元 ARM MULA 指令現在已正確彙編,其中加數暫存器作為第三個引數,結果暫存器作為第四個也是最後一個引數。在之前的版本中,這兩個含義是顛倒的。三運算元形式(其中第四個引數隱式與第三個引數相同)不受影響。使用四運算元 MULA 指令的程式碼需要更新,但我們認為這種形式很少使用。MULAWT 和 MULAWB 在所有形式中都已使用正確的順序,並且未更改。
彙編器現在支援 ADDSUBPS/PD,補齊了兩個缺失的 x86 SSE3 指令。
文件
長引數列表現在會被截斷。這提高了 go doc 在某些生成程式碼上的可讀性。
現在支援檢視結構欄位的文件。例如,go doc http.Client.Jar。
環境變數
新的 go env -json 標誌啟用 JSON 輸出,而不是預設的特定於作業系統的輸出格式。
Test
go test 命令接受一個新的 -list 標誌,該標誌接受一個正則表示式作為引數,並列印匹配的任何測試、基準或示例的名稱到標準輸出,而不執行它們。
Pprof
runtime/pprof 包生成的配置檔案現在包含符號資訊,因此可以在 go tool pprof 中檢視它們,而無需生成配置檔案的二進位制檔案。
go tool pprof 命令現在使用環境中定義的 HTTP 代理資訊,使用 http.ProxyFromEnvironment。
Vet
vet 命令已更好地整合到go 工具中,因此 go vet 現在支援所有標準構建標誌,而 vet 自己的標誌現在也可以從 go vet 以及 go tool vet 獲得。
Gccgo
由於 Go 的半年釋出計劃與 GCC 的年度釋出計劃保持一致,GCC 7 釋出版本包含 gccgo 的 Go 1.8.3 版本。我們預計下一個版本 GCC 8 將包含 gccgo 的 Go 1.10 版本。
執行時
包含內聯幀的呼叫堆疊
runtime.Callers 的使用者應避免直接檢查結果 PC 切片,而應使用 runtime.CallersFrames 獲取完整的呼叫堆疊檢視,或使用 runtime.Caller 獲取單個呼叫方的資訊。這是因為 PC 切片的單個元素無法考慮內聯幀或呼叫堆疊的其他細微差別。
具體來說,直接遍歷 PC 切片並使用 runtime.FuncForPC 等函式單獨解析每個 PC 的程式碼將錯過內聯幀。要獲取完整的堆疊檢視,此類程式碼應改用 CallersFrames。同樣,程式碼不應假定 Callers 返回的長度是呼叫深度的任何指示。它應改為計算 CallersFrames 返回的幀數。
在特定深度查詢單個呼叫方的程式碼應使用 Caller,而不是向 Callers 傳遞長度為 1 的切片。
runtime.CallersFrames 自 Go 1.7 起可用,因此程式碼可以在升級到 Go 1.9 之前進行更新。
效能
一如既往,更改通用且多樣,因此很難對效能做出精確的說明。由於垃圾收集器提速、更好的生成程式碼和核心庫中的最佳化,大多數程式應該執行得更快一些。
垃圾收集器
以前會觸發“停頓世界”垃圾收集的庫函式現在會觸發併發垃圾收集。具體來說,runtime.GC、debug.SetGCPercent 和 debug.FreeOSMemory 現在會觸發併發垃圾收集,只阻塞呼叫 goroutine 直到垃圾收集完成。
如果由於新的 GOGC 值而立即需要垃圾收集,debug.SetGCPercent 函式才會觸發垃圾收集。這使得可以即時調整 GOGC。
在使用包含許多大物件的大型(>50GB)堆的應用程式中,大物件分配效能顯著提高。
即使對於非常大的堆,runtime.ReadMemStats 函式現在也只需不到 100µs。
標準庫
透明單調時間支援
time 包現在透明地跟蹤每個 Time 值中的單調時間,使得在存在掛鐘調整的情況下計算兩個 Time 值之間的時間變得安全。有關詳細資訊,請參閱包文件和設計文件。
新的位操作包
Go 1.9 包含一個新包 math/bits,其中包含用於操作位的最佳化實現。在大多數架構上,此包中的函式還會被編譯器識別並視為內部函式,以獲得額外的效能。
測試輔助函式
新的 (*T).Helper 和 (*B).Helper 方法將呼叫函式標記為測試輔助函式。在列印檔案和行資訊時,該函式將被跳過。這允許編寫測試輔助函式,同時仍為使用者提供有用的行號。
併發對映
sync 包中的新 Map 型別是一個併發對映,具有分攤常數時間的載入、儲存和刪除操作。多個 goroutine 可以併發呼叫 Map 的方法,這是安全的。
Profiler 標籤
runtime/pprof 包現在支援向 pprof 分析器記錄新增標籤。標籤構成一個鍵值對映,用於在使用 pprof 命令檢視配置檔案時區分不同上下文中對同一函式的呼叫。pprof 包的新 Do 函式執行與某些提供的標籤關聯的程式碼。包中的其他新函式有助於使用標籤。
對庫的微小更改
與往常一樣,庫中有各種微小的更改和更新,這些都是在遵守 Go 1 相容性承諾的前提下進行的。
archive/zip
ZIP Writer 現在會在適當時設定 FileHeader.Flags 中的 UTF-8 位。
crypto/rand
在 Linux 上,Go 現在呼叫 getrandom 系統呼叫時沒有 GRND_NONBLOCK 標誌;它現在會阻塞,直到核心有足夠的隨機性。在早於 getrandom 系統呼叫的核心上,Go 繼續從 /dev/urandom 讀取。
crypto/x509
在 Unix 系統上,環境變數 SSL_CERT_FILE 和 SSL_CERT_DIR 現在可以分別用於覆蓋 SSL 證書檔案和 SSL 證書檔案目錄的系統預設位置。
FreeBSD 檔案 /usr/local/etc/ssl/cert.pem 現在包含在證書搜尋路徑中。
該包現在支援名稱約束中的排除域。除了強制執行此類約束外,如果提供的模板證書填充了新的欄位 ExcludedDNSDomains,CreateCertificate 將建立具有排除名稱約束的證書。
如果證書中存在任何 SAN 擴充套件(包括沒有 DNS 名稱的擴充套件),則將忽略 Subject 中的 Common Name。在之前的版本中,程式碼僅測試證書中是否存在 DNS 名稱 SAN。
database/sql
該包現在將在 Tx.Stmt 中使用快取的 Stmt(如果可用)。這可以防止每次呼叫 Tx.Stmt 時都重新準備語句。
該包現在允許驅動程式透過實現 driver.NamedValueChecker 來實現自己的引數檢查器。這也允許驅動程式支援 OUTPUT 和 INOUT 引數型別。當驅動程式支援時,應使用 Out 返回輸出引數。
Rows.Scan 現在可以掃描使用者定義的字串型別。以前,該包支援掃描到 type Int int64 等數字型別。現在它也支援掃描到 type String string 等字串型別。
新的 DB.Conn 方法返回新的 Conn 型別,表示來自連線池的資料庫獨佔連線。在呼叫 Conn.Close 將連線返回到連線池之前,在 Conn 上執行的所有查詢都將使用相同的底層連線。
encoding/asn1
新的 NullBytes 和 NullRawValue 表示 ASN.1 NULL 型別。
encoding/base32
新的 Encoding.WithPadding 方法增加了對自定義填充字元和停用填充的支援。
encoding/csv
新的欄位 Reader.ReuseRecord 控制對 Read 的呼叫是否可以返回一個共享前一次呼叫返回切片的底層陣列的切片,以提高效能。
fmt
現在在列印浮點數和複數時支援井號標誌('#')。它將始終為 %e、%E、%f、%F、%g 和 %G 列印小數點;它不會為 %g 和 %G 刪除尾隨零。
hash/fnv
該包現在包含 128 位 FNV-1 和 FNV-1a 雜湊支援,分別透過 New128 和 New128a 實現。
html/template
如果管道中發現預定義的轉義器(“html”、“urlquery”和“js”之一)並且與自動轉義器自行決定的不匹配,該包現在會報告錯誤。這避免了某些安全或正確性問題。現在使用這些轉義器之一總是無操作或錯誤。(無操作情況簡化了從 text/template 的遷移。)
影像
Rectangle.Intersect 方法現在在對相鄰但不重疊的矩形呼叫時返回一個零 Rectangle,如文件所述。在早期版本中,它會錯誤地返回一個空但非零的 Rectangle。
image/color
YCbCr 到 RGBA 的轉換公式已調整,以確保舍入調整涵蓋完整的 [0, 0xffff] RGBA 範圍。
image/png
新的 Encoder.BufferPool 欄位允許指定一個 EncoderBufferPool,編碼器在編碼 PNG 影像時將使用它來獲取臨時 EncoderBuffer 緩衝區。使用 BufferPool 減少了編碼多個影像時執行的記憶體分配數量。
該包現在支援解碼透明的 8 位灰度(“Gray8”)影像。
math/big
新的 IsInt64 和 IsUint64 方法報告 Int 是否可以表示為 int64 或 uint64 值。
mime/multipart
新的 FileHeader.Size 欄位描述了多部分訊息中檔案的大小。
net
新的 Resolver.StrictErrors 控制 Go 內建 DNS 解析器如何在由多個子查詢(例如 A+AAAA 地址查詢)組成的查詢期間處理臨時錯誤。
新的 Resolver.Dial 允許 Resolver 使用自定義撥號函式。
JoinHostPort 現在只在主機包含冒號時將地址放在方括號中。在之前的版本中,如果地址包含百分號('%')也會將其括在方括號中。
新的方法 TCPConn.SyscallConn、IPConn.SyscallConn、UDPConn.SyscallConn 和 UnixConn.SyscallConn 提供了對連線底層檔案描述符的訪問。
現在,在用 Listen(“tcp”, “:0”) 建立監聽器後,使用 (*TCPListener).String() 獲取的地址呼叫 Dial 是安全的。以前,在某些具有半配置 IPv6 堆疊的機器上會失敗。
net/http
用於 Cookie 和 Set-Cookie 頭的 Cookie.String 方法現在會在值包含空格或逗號時將值用雙引號括起來。
伺服器更改
-
ServeMux現在在匹配處理程式時忽略主機頭中的埠。對於CONNECT請求,主機未經修改地進行匹配。 -
新的
Server.ServeTLS方法包裝了Server.Serve,並增加了 TLS 支援。 -
Server.WriteTimeout現在適用於 HTTP/2 連線,並按流強制執行。 - HTTP/2 現在預設使用優先順序寫入排程器。幀按照 RFC 7540 第 5.3 節所述的 HTTP/2 優先順序進行排程。
-
StripPrefix返回的 HTTP 處理程式現在使用修改後的原始*http.Request克隆呼叫其提供的處理程式。任何將按請求狀態儲存在以*http.Request為鍵的對映中的程式碼都應改用Request.Context、Request.WithContext和context.WithValue。 -
LocalAddrContextKey現在包含連線的實際網路地址,而不是監聽器使用的介面地址。
客戶端和傳輸更改
-
當
Transport.Proxy返回的 URL 方案為socks5時,Transport現在支援透過 SOCKS5 代理發出請求。
net/http/fcgi
新的 ProcessEnv 函式返回與 HTTP 請求關聯的 FastCGI 環境變數,對於這些環境變數,沒有合適的 http.Request 欄位,例如 REMOTE_USER。
net/http/httptest
新的 Server.Client 方法返回一個配置用於向測試伺服器發出請求的 HTTP 客戶端。
新的 Server.Certificate 方法返回測試伺服器的 TLS 證書(如果有)。
net/http/httputil
ReverseProxy 現在代理所有 HTTP/2 響應尾部,即使是那些未在初始響應頭中宣告的尾部。這些未宣告的尾部由 gRPC 協議使用。
os
os 包現在使用內部執行時輪詢器進行檔案 I/O。這減少了對管道進行讀/寫操作所需的執行緒數,並消除了一個 goroutine 關閉檔案而另一個 goroutine 使用該檔案進行 I/O 時的競爭條件。
在 Windows 上,Args 現在在沒有 shell32.dll 的情況下填充,將程序啟動時間縮短了 1-7 毫秒。
os/exec
os/exec 包現在阻止子程序使用任何重複的環境變數建立。如果 Cmd.Env 包含重複的環境鍵,則只使用切片中每個重複鍵的最後一個值。
os/user
當 CGO_ENABLED=0 時,Lookup 和 LookupId 現在在 Unix 系統上透過讀取 /etc/passwd 檔案工作。
當 CGO_ENABLED=0 時,LookupGroup 和 LookupGroupId 現在在 Unix 系統上透過讀取 /etc/group 檔案工作。
reflect
新的 MakeMapWithSize 函式建立具有容量提示的對映。
runtime
執行時生成並在配置檔案中記錄的跟蹤堆疊現在在存在內聯的情況下是準確的。為了以程式設計方式檢索跟蹤堆疊,應用程式應該使用 runtime.CallersFrames 而不是直接遍歷 runtime.Callers 的結果。
在 Windows 上,Go 不再在程式空閒時強制系統計時器以高解析度執行。這應該會減少 Go 程式對電池壽命的影響。
在 FreeBSD 上,GOMAXPROCS 和 runtime.NumCPU 現在基於程序的 CPU 掩碼,而不是 CPU 的總數。
執行時初步支援 Android O。
runtime/debug
使用負值呼叫 SetGCPercent 不再立即執行垃圾收集。
runtime/trace
執行跟蹤現在顯示標記輔助事件,這表示當應用程式 goroutine 因為分配過快而被強制協助垃圾收集時。
“清掃”事件現在包含為分配查詢空閒空間的整個過程,而不是記錄每個單獨被清掃的 span。這減少了在跟蹤分配密集型程式時的分配延遲。清掃事件顯示清掃了多少位元組以及回收了多少位元組。
sync
Mutex 現在更加公平。
syscall
新的欄位 Credential.NoSetGroups 控制 Unix 系統在啟動新程序時是否進行 setgroups 系統呼叫來設定補充組。
新的欄位 SysProcAttr.AmbientCaps 允許在 Linux 4.3+ 上建立新程序時設定環境能力。
在 64 位 x86 Linux 上,透過使用 CLONE_VFORK 和 CLONE_VM 優化了程序建立延遲。
新的 Conn 介面描述了 net 包中的某些型別,這些型別可以使用新的 RawConn 介面提供對其底層檔案描述符的訪問。
testing/quick
該包現在在生成 int64 和 uint64 隨機數時選擇完整範圍內的值;在早期版本中,生成的值總是限制在 [-262, 262) 範圍內。
在之前的版本中,使用 nil Config.Rand 值會導致使用固定的確定性隨機數生成器。它現在使用以當前時間作為種子的隨機數生成器。對於舊的行為,請將 Config.Rand 設定為 rand.New(rand.NewSource(0))。
text/template
空塊的處理(因 Go 1.8 更改導致結果依賴於模板順序而損壞)已修復,恢復了舊的 Go 1.7 行為。
time
新的方法 Duration.Round 和 Duration.Truncate 處理將持續時間舍入和截斷為給定持續時間的倍數。
現在在 Wine 下獲取時間並休眠工作正常。
如果 Time 值具有單調時鐘讀數,則其字串表示形式(由 String 返回)現在包含一個最終欄位 "m=±value",其中 value 是格式化為秒的十進位制數的單調時鐘讀數。
包含的 tzdata 時區資料庫已更新到 2017b 版本。一如既往,只有在系統尚無該資料庫時才使用它。