Go 1.10 發行說明

Go 1.10 簡介

最新 Go 版本 1.10 版在 Go 1.9 發佈後六個月推出。其大部分變更涉及工具鏈、執行階段與函式庫的實作。一如往常,此次發行維持 Go 1 相容性保證。我們預期幾乎所有 Go 程式都將持續如以往般進行編譯與執行。

此次發行優化 已建置套件快取、新增 成功測試結果快取,在測試期間 自動執行 vet 程式,並允許 使用 cgo 直接在 Go 與 C 之間傳遞字串值。新增的 安全編譯器選項硬編碼設定 可能會導致在使用舊版本成功建置的程式碼中發生意外 invalid flag 錯誤。

語言變更

語言規格並未進行大幅度的變更。

已釐清未定義常數位移角案例,並根據釐清後的結果更新編譯器,以允許使用指標表示式 x[1.0 << s],其中 s 為一個無符號整數; go/types 套件已執行此動作。

方法表示式的語法已更新,放寬語法限制以允許任何類型表示式作為接受參數;這與編譯器先前建立的實作相符。例如,struct{io.Reader}.Read 是目前編譯器已接受的有效方法表示式(儘管並不常見),且現已獲得語言語法的允許。

通訊埠

此版本中沒有新的支援作業系統或處理器架構。大部分工作專注於加強對現有通訊埠的支援,特別是 組譯器中的新指令,和編譯器產生的程式碼的改進。

如同 Go 1.9 版本注意事項 所發布,Go 1.10 現在需要 FreeBSD 10.3 或更新版本;已移除 FreeBSD 9.3 的支援。

Go 現在能在 NetBSD 上再次執行,但需要尚未發布的 NetBSD 8。只有 GOARCH amd64386 已修正。arm 通訊埠仍已損壞。

在 32 位元的 MIPS 系統中,新的環境變數設定 GOMIPS=hardfloat(預設)和 GOMIPS=softfloat 會選取是否使用硬體指令或軟體模擬來執行浮點運算。

Go 1.10 是最後一個可以在 OpenBSD 6.0 上執行的版本。Go 1.11 將需要 OpenBSD 6.2。

Go 1.10 是最後一個可以在 OS X 10.8 Mountain Lion 或 OS X 10.9 Mavericks 上執行的版本。Go 1.11 將需要 OS X 10.10 Yosemite 或更新版本。

Go 1.10 是最後一個可以在 Windows XP 或 Windows Vista 上執行的版本。Go 1.11 將需要 Windows 7 或更新版本。

工具

預設 GOROOT 和 GOTMPDIR

如果環境變數 $GOROOT 未設定,go 工具以前會使用在編譯工具鏈過程中設定的預設 GOROOT。現在,在採用那個預設值之前,go 工具會嘗試從它自己的可執行路徑推演出 GOROOT。這允許二進制發行版解壓縮到檔案系統中的任何位置,然後在不特別設定 GOROOT 的情況下使用。

預設情況下,go 工具會在系統暫存目錄(例如,Unix 中的 $TMPDIR)中建立它的暫存檔案和目錄。如果已設定新的環境變數 $GOTMPDIR,go 工具會改在其目錄中建立它的暫存檔案和目錄。

建置和安裝

go build 指令現在會純粹根據原始檔案、指定的建置旗標和儲存在已編譯套件中的資料,偵測過期的套件。修改時間不再被諮詢或與之相關。在因某種原因(例如,建置旗標中的變更)而修改時間具有誤導性的情況下,用於強制重新建置的舊建議,例如加上 -a 已不再必要:建置現在總是能偵測到套件是否必須重新建置。(如果您觀察到有其他狀況,請提交錯誤。)

go build -asmflags-gcflags-gccgoflags-ldflags 選項現在預設只套用於命令列上直接列出的套件。例如,go build -gcflags=-m mypkg 會在建置 mypkg 時將 -m 旗標傳遞給編譯器,但不會傳遞給依賴關係。新的更通用的格式 -asmflags=pattern=flags(其他選項也類似),只會對符合模式的套件套用 flags。例如:go install -ldflags=cmd/gofmt=-X=main.version=1.2.3 cmd/... 會安裝與 cmd/... 相符的所有指令,但只會將 -X 選項套用於 cmd/gofmt 的連結器旗標。詳情請參閱 go help build

go build 指令現在會維護最近建置套件的快取,與 $GOROOT/pkg$GOPATH/pkg 中的已安裝套件分開。快取的效果應該是加快未明確安裝套件的建置,或是在不同原始碼副本之間切換時(例如在版本控制系統中前後切換不同分支時)。舊有的建議,即加入 -i 旗標以提升速度,例如 go build -igo test -i,現在已不再必要:不使用 -i 時,建置的速度一樣快。詳情請參閱 go help cache

go install 指令現在只會安裝命令列上直接列出的套件和指令。例如,go install cmd/gofmt 會安裝 gofmt 程式,但不會安裝它所依賴的任何套件。新的建置快取會讓未來的指令執行速度,即使已安裝依賴關係,也能和以前一樣快。若要強制安裝依賴項,請使用新的 go install -i 旗標。一般而言,安裝依賴項套件並不是必要的,而在未來的版本中,已安裝套件的概念可能會消失。

為了支援這些改善,go build 實作的許多細節都已變更。這些變更暗示的一個新需求是,純二進位套件現在必須在其 stub 原始碼中宣告精確的 import 區塊,才能在使用純二進位套件連結程式時,讓這些 import 可用。詳情請參閱 go help filetype

測試

go test 指令現在會快取測試結果:如果測試可執行檔和命令列與之前的執行相同,而且該執行所查詢的檔案和環境變數也未變更,go test 會印出先前的測試輸出,並將經過時間置換為字串「(快取)」。測試快取僅適用於測試成功結果;僅適用於具有明確程式庫清單的go test 指令;且僅適用於使用以下測試旗標子集的命令列:-cpu-list-parallel-run-short-v。繞過測試快取的慣用方法是使用 -count=1

go test 指令現在會在測試程式庫之前自動執行 go vet,以在執行測試之前找出重大問題。任何此類問題都會視為建置錯誤,並防止執行測試。僅有極具信賴度的 go vet 檢查子集會啟用於這項自動檢查。若要停用執行 go vet,請使用 go test -vet=off

go test -coverpkg 旗標現在會將其引數當作逗號分隔的清單,用於與每個測試的相依關係相符,而非視為要重新載入的程式庫清單。例如,go test -coverpkg=all 現在是有意義的方法,可以用來執行已針對測試程式庫及所有相關依賴項啟用涵蓋範圍的測試。此外,go test -coverprofile 選項現在支援在執行多項測試時使用。

如果因逾時而導致失敗,現在測試較有可能在結束前寫入自己的設定檔。

go test 指令現在會永遠合併來自既定測試二進制執行項目的標準輸出和標準錯誤,並將兩者寫入 go test 的標準輸出。在過往版本中,go test 大多數時候只會套用此合併。

go test -v 輸出現在包含 PAUSECONT 狀態更新列,以標記 平行測試 暫停和繼續時的時間點。

新的 go test -failfast 旗標會在任何測試失敗後停用執行其他測試。請注意,與失敗測試平行執行的測試仍准予完成。

最後,新的 go test -json 旗標會透過新指令 go tool test2json 篩選測試輸出,以產生測試執行的機器可讀 JSON 格式描述。這允許在 IDE 和其他工具中建立豐富的測試執行簡報。

有關所有這些變更的更多詳細資料,請參閱 go help testtest2json 文件

Cgo

現在會檢查由 cgo 使用 #cgo CFLAGS 指定的選項和類似選項,以符合允許的選項清單。這關閉了一個安全漏洞,已下載的套件會在建置其的機器上,使用 -fplugin 等編譯器選項來執行任意程式碼。這可能會導致建置錯誤,例如 invalid flag in #cgo CFLAGS。有關更多背景資訊,以及如何處理此錯誤,請參閱 https://go.dev.org.tw/s/invalidflag

Cgo 現在使用 Go 型別別名實作 C typedef,例如 “typedef X Y”,以便 Go 程式碼可以互換地使用型別 C.XC.Y。它現在也支援使用無引數的函數式巨集。此外,文件已更新以澄清 Go 結構和 Go 陣列不受 cgo 匯出的函數型別簽章支援。

Cgo 現在支援直接從 C 存取 Go 字串值。C 前置宣告中的函數可能會使用型別 _GoString_ 來接受 Go 字串做為引數。C 程式碼可能會呼叫 _GoStringLen_GoStringPtr,以便直接存取字串的內容。值型別 _GoString_ 可能會傳入呼叫匯出的 Go 函數,而這個函數接收 Go 型別 string 的引數。

在工具鏈開機期間,環境變數 CCCC_FOR_TARGET 分別指定產生的工具鏈將用於主機和目標建置的預設 C 編譯器。但是,如果工具鏈將與多個目標一起使用,可能有必要為每個目標指定不同的 C 編譯器(例如,darwin/arm64 不同於 linux/ppc64le 的編譯器)。新的環境變數組 CC_FOR_goos_goarch 允許為每個目標指定不同的預設 C 編譯器。請注意,這些變數僅套用於工具鏈開機程式,以便設定產生的工具鏈所使用的預設值。稍後 go build 命令會使用 CC 環境變數或內建的預設值。

Cgo 現在會將一些通常對應於 Go 中指標型別的 C 型別轉換成 uintptr。這些型別包括 Darwin 的 CoreFoundation 架構中的 CFTypeRef 階層,以及 Java 的 JNI 介面中的 jobject 階層。

這些型別在 Go 端必須是 uintptr,否則它們會混淆 Go 垃圾收集器;它們有時並非真正的指標,而是一種編碼在指標大小整數中的資料結構。不能將指向 Go 記憶體的指標儲存在這些 uintptr 值中。

由於此變更,需要受到影響的型別值用常數 0 初始化,而不是常數 nil。Go 1.10 提供 gofix 模組來協助重寫

go tool fix -r cftype <pkg>
go tool fix -r jni <pkg>

有關詳細資訊,請參閱 cgo 文件

文件

go doc 工具現在將傳回 T*T 陣列的函式加入 T 類型的顯示中,類似於函式傳回單一 T*T 結果的現有行為。例如

$ go doc mail.Address
package mail // import "net/mail"

type Address struct {
    Name    string
    Address string
}
    Address represents a single mail address.

func ParseAddress(address string) (*Address, error)
func ParseAddressList(list string) ([]*Address, error)
func (a *Address) String() string
$

以前,ParseAddressList 只會顯示於套件概觀中 (go doc mail)。

修正

go fix 工具現在將 "golang.org/x/net/context" 的匯入替換為 "context"。 (在後者中轉遞別名會使其與使用 Go 1.9 或更新版本時完全等同於前者)

取得

go get 命令現在支援 Fossil 原始程式碼存放庫。

Pprof

runtime/pprof 套件產生的封鎖及互斥鎖的描述檔現在包含符號資訊,因此它們可以用 go tool pprof 在不使用產生描述檔的二進位檔的情況下檢視。 (Go 1.9 中已經將所有其他描述檔類型變更為包含符號資訊)

go tool pprof 描述檔視覺化程式已從 github.com/google/pprof 更新至 git 版本 9e20b5b (2017-11-08),其中包含更新的網路介面。

Vet

go vet 命令在檢查套件時現在總是能存取完整且最新的型別資訊,即使是在套件中使用 cgo 或供應商匯入的情況下也是如此。因此,報告應該會更準確。請注意,只有 go vet 能夠存取此資訊;更底層的 go tool vet 無法存取此資訊,應避免使用,除非處理時在 vet 本身。 (在 Go 1.9 中,go vet 提供存取與 go tool vet 相同所有旗標的權限)

診斷

此版本包括一個 可用的 Go 程式診斷工具概述 的新資訊。

Gofmt

Go 來源程式碼的預設格式設定中的兩個次要詳細資訊已變更。第一,某些複雜的三個索引陣列表示式以前會以 x[i+1 : j:k] 的格式設定,而現在會以更一致的間隔格式化:x[i+1 : j : k]。第二,寫在單一行上的單一方法介面字面值,有時候會用於類型斷言中,現在不會再分拆成多行。

請注意,此類 gofmt 的小更新預計會不時出現。我們一般建議不要編寫會檢查原始碼是否與特定 gofmt 版本的輸出來相符的系統。例如,如果對已簽入儲存庫的任何程式碼進行「適當格式化」就失敗的持續整合測試,本質上就脆弱且不建議使用。

如果多個程式必須就使用哪個版本的 gofmt 來格式化原始檔達成共識,我們建議透過安排呼叫同一個 gofmt 二進位檔來達成。例如,在 Go 開放原始碼儲存庫中,我們的 Git 預提交掛鉤是以 Go 編寫的,可以直接匯入 go/format,但它會呼叫在目前路徑找到的 gofmt 二進位檔,因此預提交掛鉤不必在每次 gofmt 變更時重新編譯。

編譯器工具鏈

編譯器包含多項對產生式程式碼效能的改善,且在受支援的架構中分布良好。

二進位檔中記錄的 DWARF 偵錯資訊以幾種方式改善:常數值現在會進行記錄;行號資訊更準確,因此在程式上進行原始碼步驟操作更有效率;現在會將每個套件視為其自己的 DWARF 編譯單位。

各種 建置模式 已移植到更多系統。具體地說,c-shared 現在可在 linux/ppc64lewindows/386windows/amd64 上運作;pie 現在可在 darwin/amd64 上運作,也會在所有系統上強制使用外部連結;plugin 現在可在 linux/ppc64ledarwin/amd64 上運作。

linux/ppc64le 埠現在需要將外部連結用於任何使用 cgo 的程式,甚至是標準函式庫的用法。

組譯器

對於 ARM 32 位元埠,組譯器現在支援 BFCBFIBFXBFXUFMULADFMULAFFMULSDFMULSFFNMULADFNMULAFFNMULSDFNMULSFMULADMULAFMULSDMULSFNMULADNMULAFNMULDNMULFNMULSDNMULSFXTABXTABUXTAHXTAHU 指令。

對於 ARM 64 位元埠,組譯器現在支援 VADDVADDPVADDVVANDVCMEQVDUPVEORVLD1VMOVVMOVIVMOVSVORRVREV32VST1 指令。

位於 PowerPC 64 位元埠的組合語言組譯器現在支援 POWER9 指令 ADDEXCMPEQBCOPYDARNLDMXMADDHDMADDHDUMADDLDMFVSRLDMTVSRDDMTVSRWSPASTECCVCMPNEZBVCMPNEZBCCVMSUMUDM

位於 S390X 埠的組合語言組譯器現在支援 TMHHTMHLTMLHTMLL 指令。

位於 X86 64 位元埠的組合語言組譯器現在支援 359 個新指令,其中包括完整的 AVX、AVX2、BMI、BMI2、F16C、FMA3、SSE2、SSE3、SSSE3、SSE4.1 和 SSE4.2 延伸組。組譯器也不再將 MOVL $0, AX 實作為 XORL 指令,藉此避免意外清除條件旗標。

Gccgo

由於 Go 半年一次的發行時程與 GCC 一年一次的發行時程如此吻合,因此 GCC 7 發行版本包含了 Go 1.8.3 版的 gccgo。我們預計下一個版本 GCC 8,將會包含 Go 1.10 版的 gccgo。

執行時期

LockOSThreadUnlockOSThread 進行巢狀呼叫時,其行為已改變。這些函式控制是否將一組常式鎖定到特定作業系統執行緒,好讓一組常式只在該執行緒上執行,而該執行緒只會執行那一組常式。之前,如果連續呼叫 LockOSThread 超過一次,等同於呼叫一次;而單次呼叫 UnlockOSThread 總是會解除對該執行緒的鎖定。現在,這些呼叫會巢狀:如果呼叫了多次 LockOSThread,則必須呼叫相同次數的 UnlockOSThread,才能解除對該執行緒的鎖定。絕不會巢狀呼叫這些函式的現有程式碼將維持正確無誤。而錯誤假設這些函式會巢狀的程式碼,則會變成正確無誤。在公開的 Go 程式碼中,大部分使用這些函式的範例都屬於第二類。

由於 LockOSThreadUnlockOSThread 的其中一個常見用法,是要允許 Go 程式碼可靠修改執行緒的局部狀態 (例如 Linux 或 Plan 9 名稱空間),因此執行時期現在將鎖定的執行緒視為不適合重用或用於建立新的執行緒。

堆疊追蹤不再包含隱含的包裝函式 (以前標示為 <autogenerated>),除非故障或驚慌發生在包裝函式本身。因此,傳遞給諸如 Caller 等函式的跳過計數,現在應該總是與所寫程式碼的結構相符,而不是取決於最佳化決策和實作的詳細資料。

對垃圾回收器進行調整,以降低其對配置延遲期的影響。其運作時現使用較小比例的整體 CPU,但執行時間可能較長。垃圾回收器所用掉的總體 CPU 資源並未有明顯改變。

若未設定變數 $GOROOTGOROOT 功能現在採用在呼叫程式編譯當時的 GOROOTGOROOT_FINAL 為預設值。先前為使用編譯呼叫程式之工具鏈編譯當時的 GOROOTGOROOT_FINAL

取消對 GOMAXPROCS 設定值上限的限制。(在 Go 1.9 中,限制值為 1024。)

效能

一如既往地,這些變更多樣且廣泛,因此很難做出精準的效能聲明。大多數程式應會執行得稍快一點,原因在於垃圾回收器的加速、更好的產出程式碼,以及核心程式庫的最佳化。

垃圾回收器

當垃圾回收器處於活動狀態時,許多應用程式應會體驗到低上許多的配置延遲期與整體效能成本。

標準函式庫

標準函式庫的變更都算小。在 bytesnet/url 中的變更最有可能需要更新既有的程式。

函式庫的小變更

一如往常,對函式庫進行了種種小變更與更新,考量在 Go 1 下 相容性的承諾

archive/tar

整體而言,特別標頭格式的處理獲得顯著的改善與擴充。

FileInfoHeader 向來會將其 os.FileInfo 引數(精確來說,是 FileInfoSys 方法所回傳的系統依賴資訊)中的 Unix UID 和 GID 編號記錄在回傳的 Header 裡。現在,它也會記錄與這些 ID 對應的使用者和群組名稱,以及裝置檔案的主要與次要裝置編號。

Header 的新欄位 Header.Format 型態為 Format,控制 Writer 使用哪種 tar 標頭格式。預設值(一如往常)是選取可以編碼標頭所需欄位的支援度最高標頭類型(若可能,為 USTAR;否則若可能,為 PAX;否則,為 GNU)。Reader 會為它讀取的每個標頭設定 Header.Format

ReaderWriter 現在支援使用新的欄位 Header.PAXRecords 任意 PAX 記錄,這是既有 Xattrs 欄位的概化。

Reader 不再堅持 GNU 標頭中的檔案名稱或連結名稱必須為有效的 UTF-8。

寫入 PAX 或 GNU 格式的標頭時,Writer 現在包括已設定(若有)的 Header.AccessTimeHeader.ChangeTime 欄位。寫入 PAX 格式的標頭時,這些時間包含毫秒以下的精度。

archive/zip

Go 1.10 支援更完整的時間和 ZIP 檔案中的字元集編碼。

原始 ZIP 格式使用標準 MS-DOS 編碼,將年、月、日、時、分和秒編碼成兩個 16 位元值的欄位。這種編碼無法表示時區或奇數秒,所以有多個擴充功能可以允許更豐富的編碼。在 Go 1.10 中,ReaderWriter 現在支援普遍理解的 Info-Zip 擴充功能,該擴充功能將時間以 32 位元 Unix 「自紀元以來秒數」的形式獨立編碼。FileHeader 的新 Modified 欄位為 time.Time 類型,淘汰了 ModifiedTimeModifiedDate 欄位,這些欄位會繼續儲存 MS-DOS 編碼。ReaderWriter 現在採用常見慣例,即儲存時區無關 Unix 時間的 ZIP 檔案也會在 MS-DOS 欄位中儲存當地時間,這樣可以推算出時區偏移量。為了相容性,ModTimeSetModTime 方法的行為與較早版本相同;新的程式碼應該直接使用 Modified

ZIP 檔案中每個檔案的標頭有一個旗標位元,指示名稱和註解欄位編碼為 UTF-8,而不是系統特定的預設編碼。在 Go 1.8 及更早版本中,Writer 從未設定 UTF-8 位元。在 Go 1.9 中,Writer 變更為幾乎每次都設定 UTF-8 位元。這中斷了建立包含 Shift-JIS 檔案名稱的 ZIP 檔案。在 Go 1.10 中,Writer 現在只在名稱和註解欄位都是有效的 UTF-8 且至少有一個非 ASCII 時才會設定 UTF-8 位元。由於非 ASCII 編碼極少看起來像是有效的 UTF-8,所以新的啟發式演算法應該在幾乎所有情況下都是正確的。將 FileHeader 的新 NonUTF8 欄位設定為 true,可以完全停用該檔案的啟發式演算法。

此外,Writer 現在支援設定中心目錄結束記錄的註解欄位,方法是呼叫 Writer 新的 SetComment 方法。

bufio

新的 Reader.SizeWriter.Size 方法回報 ReaderWriter 的基本緩衝區大小。

bytes

FieldsFieldsFuncSplitSplitAfter 函數總是會傳回其輸入的子切片。Go 1.10 將每個傳回的子切片變更為容量等於其長度,以便附加到一個子切片不會覆寫原始輸入中的鄰接資料。

crypto/cipher

NewOFB 現在如果提供長度不正確的初始化向量,就會發生恐慌,一如封裝中的其他建構函數一直以來所發生的。(先前的行為是傳回一個 nil 的 Stream 實作。)

crypto/tls

使用 TLS 1.2 時,TLS 伺服器現在會宣告支援 SHA-512 簽章。伺服器早已支援 SHA-512 簽章,但一些用戶端只有在伺服器明確宣告支援時,才會選擇使用這些簽章。

crypto/x509

Certificate.Verify 現在會對憑證中包含的所有名稱強制執行名稱約束,而不僅僅是用戶端已詢問過的一個名稱。同理,現在會一次檢查所有已擴充的使用限制。因此,在驗證憑證後,現在可以完全信任憑證。不再需要為每個額外名稱或金鑰使用重新驗證憑證。

現在,已剖析的憑證也會報告 URI 名稱及 IP、電子郵件和 URI 約束,使用新的 Certificate 欄位 URIsPermittedIPRangesExcludedIPRangesPermittedEmailAddressesExcludedEmailAddressesPermittedURIDomainsExcludedURIDomains。現在會拒絕含有那些欄位無效值的憑證。

新的 MarshalPKCS1PublicKeyParsePKCS1PublicKey 函數會將 RSA 公開金鑰轉換成 PKCS#1 編碼形式,也會將 PKCS#1 編碼形式轉換成 RSA 公開金鑰。

新的 MarshalPKCS8PrivateKey 函數會將私密金鑰轉換成 PKCS#8 編碼形式。(ParsePKCS8PrivateKey 自 Go 1 以來便已存在。)

crypto/x509/pkix

Name 現在實作一個 String 方法,該方法會以標準的 RFC 2253 格式設定 X.509 識別名稱。

database/sql/driver

目前保有由 driver.Rows.Next 提供的目的地緩衝區的驅動程式,應該確保它們不再寫入在那通話之外指派給目標陣列的緩衝區。驅動程式在關閉 driver.Rows 時,必須小心底層緩衝區不會被修改。

供想要為其客戶建立sql.DB之驅動程式,目前可實作Connector介面並呼叫新的sql.OpenDB函數,而非需要將所有組態編碼成傳遞給sql.Open的字串。

在每次使用sql.Conn而非每次使用sql.DB只分析組態字串一次的驅動程式,或是想要存取每個sql.Conn的基礎內容的驅動程式,可以讓其Driver實作同時實作DriverContext的新OpenConnector方法。

實作ExecerContext的驅動程式不再需要實作Execer,類似地,實作QueryerContext的驅動程式不再需要實作Queryer。先前即使實作了基於內容的介面,除非也實作了非基於內容的介面,否則這些介面都會被忽略。

為允許驅動程式能更好分離使用快取驅動程式連線的相異客戶,如果Conn實作新的SessionResetter介面,則database/sql現在會在重先使用Conn進行新的客戶前呼叫ResetSession

debug/elf

此版本新增了 348 個新的重配置常數,分別分成重配置類型R_386R_AARCH64R_ARMR_PPC64R_X86_64

debug/macho

Go 1.10 新增支援,使用Section結構的新Relocs欄位,以及新的RelocRelocTypeARMRelocTypeARM64RelocTypeGenericRelocTypeX86_64類型及關聯常數,從 Mach-O 區段讀取重配置。

Go 1.10 也新增支援LC_RPATH載入命令,由RpathCmdRpath類型表示,以及新的命名常數,針對標頭中找到的各種旗標位元。

encoding/asn1

Marshal現在正確編碼含有星號的字串,做為 UTF8String 類型而非 PrintableString,除非字串在結構欄位中,有標記強制使用 PrintableString。Marshal現在也尊重新含有application指令的結構標記。

新的 MarshalWithParams 函式會將其引數編組,就像附加的參數對應到其相關結構欄位的標籤一樣。

Unmarshal 現在會根據 explicittag 指令來符合結構欄位的標籤。

MarshalUnmarshal 現在都支援新的結構欄位標籤 numeric,用來表示 ASN.1 的 NumericString。

encoding/csv

Reader 現在禁止使用不合理的 CommaComment 設定,例如 NUL、換行符號、新行符號、無效符號和 Unicode 替換字元,或將 CommaComment 設定成彼此相等。

如果一個 CSV 記錄有語法錯誤且橫跨多個輸入行,ParseError 的新欄位 StartLine,現在會回報記錄開始的行數。

encoding/hex

新函式 NewEncoderNewDecoder 可提供用來從十六進制進行串流轉換的功能,類似 encoding/base32encoding/base64 中已有的等效函式。

DecodeDecodeString 函式遇到格式錯誤的輸入時,現在會回傳已轉換的位元組數,以及錯誤訊息。以前在發生任何錯誤時,它們總是會回傳 0。

encoding/json

Decoder 新增一個新方法 DisallowUnknownFields,可用來回報輸入含有不明 JSON 欄位時,發生解碼錯誤。(預設行為一直都是捨棄不明欄位。)

由於 修正了一個 reflect 錯誤 的緣故,Unmarshal 無法再解碼成內嵌在非公開結構型別的指標內的欄位,因為它無法初始化非公開的內嵌指標來指向新的儲存區。現在,Unmarshal 會在此情況下回傳一個錯誤。

encoding/pem

EncodeEncodeToMemory 在遇到無法編碼成 PEM 資料的區塊時,不再會產生部分輸出。

encoding/xml

新的函式 NewTokenDecoder 類似於 NewDecoder,不過是用來建立一個從 TokenReader 進行讀取的解碼器,而不是從格式化為 XML 的位元組串流進行讀取。其目的是在讓客戶端函式庫中可以建立 XML 串流轉換器。

flag

預設的 Usage 函式現會將其第一行輸出列印至 CommandLine.Output(),而非預設為 os.Stderr,如此一來,當用戶使用 CommandLine.SetOutput 時,訊息才可正確重新導向。

PrintDefaults 現已在標誌使用字串的新行後適當地加入縮排,這樣多行式使用字串才能漂亮地顯示。

FlagSet 新增了 ErrorHandlingNameOutput 等新方法,用來擷取傳遞給 NewFlagSetFlagSet.SetOutput 的設定。

go/doc

為了支援上述的 doc 變更,可傳回 T*T**T 等切片的函式現會出現在 TTypeFuncs 清單,而非出現在 PackageFuncs 清單。

go/importer

For 函式現接受非空值的查詢引數。

go/printer

上面 gofmt 區段 討論到 Go 原始碼預設格式化的變更已在 go/printer 套件中實作,也影響到更高等級的 go/format 套件的輸出。

hash

Hash 介面的實作現已建議實作 encoding.BinaryMarshalerencoding.BinaryUnmarshaler,以允許儲存和重新建立它們的內部狀態,而標準函式庫中的所有實作(hash/crc32crypto/sha256 等)現已實作這些介面。

html/template

新的 Srcset 內容類型可在 img 標記的 srcset 屬性內適當地處理值。

math/big

Int 現在在 SetStringText 方法中支援轉換為 2 到 62 進位制,並從這些進位制轉換。(之前只允許 2 到 36 進位制。)MaxBase 常數的值已更新。

Int 新增了一個 CmpAbs 新方法,這個方法就像 Cmp,但只比對其引數的絕對值(而非符號)。

Float 新增一個 Sqrt 新方法,用來計算平方根。

math/cmplx

複數的 AsinAsinhAtanSqrt 中的分支割線和其他邊界情況已修正,以符合 C99 標準中使用的定義。

math/rand

新的 Shuffle 函式和對應的 Rand.Shuffle 方法會將輸入順序洗牌。

math

新的函式 RoundRoundToEven 會將其引數四捨五入至最近的浮點整數值;Round 會將半整數四捨五入至較大的整數鄰近值(遠離 0),而 RoundToEven 會將半整數四捨五入至偶數整數鄰近值。

新的函式 ErfinvErfcinv 會計算反誤差函數與反互補誤差函數。

mime/multipart

Reader 現在接受檔案名稱屬性為空的區段。

mime

ParseMediaType 現在會略過無效屬性值;之前會回傳這些值作為空字串。

net

此套件中的 ConnListener 實作現在保證在 Close 回傳時,底層的檔案描述器已關閉。(在較早的版本中,如果 Close 停止其他 goroutine 中待處理的 I/O,檔案描述器可能會在 Close 回傳後不久,在其中一個 goroutine 中關閉。)

TCPListenerUnixListener 現在實作 syscall.Conn,以便使用 syscall.RawConn.Control 設定底層檔案描述器的選項。

Pipe 回傳的 Conn 實作現在支援設定讀取和寫入截止時間。

IPConn.ReadMsgIPIPConn.WriteMsgIPUDPConn.ReadMsgUDPUDPConn.WriteMsgUDP 方法現在已在 Windows 上實作。

net/http

在用戶端方面,現在可以透過 https:// URL 指定 HTTP 代理(通常由 ProxyFromEnvironment 設定),表示用戶端透過 HTTPS 連線到代理程式,再發出標準的代理 HTTP 要求。(之前,HTTP 代理 URL 必須以 http://socks5:// 開頭。)

在伺服器端,FileServer 及其單一檔案等效版本 ServeFile 會對 HEAD 要求套用 If-Range 檢查。FileServer 現在會將目錄讀取失敗訊息回報至 ServerErrorLog。此外,內容提供處理常式現在會在提供零長度內容時略過 Content-Type 標頭。

ResponseWriterWriteHeader 方法現已廢棄,如果傳遞不合法的狀態碼 (非 3 碼),則會觸發恐慌。

Handler 未寫入任何輸出時,Server 將不再新增隱含的 Content-Type。

Redirect 現已在寫入 HTTP 回應之前設定 Content-Type 標頭。

net/mail

ParseAddressParseAddressList 現已支援各種過時的位址格式。

net/smtp

Client 新增一個 Noop 方法,以測試伺服器是否仍然回應。此外,它現在也能防範在輸入 HelloVerify 方法時可能發生的 SMTP 注入攻擊。

net/textproto

ReadMIMEHeader 現已拒絕開頭是續行 (縮排) 標頭行的任何標頭。之前,具有縮排第一行的標頭被視作第一行未縮排。P>

net/url

ResolveReference 現已在目標 URL 中保留多個開頭斜線。之前會將多個開頭斜線改寫成單一斜線,導致 http.Client 錯誤地遵循特定重定向。

例如,這個程式碼的輸出已變更

base, _ := url.Parse("http://host//path//to/page1")
target, _ := url.Parse("page2")
fmt.Println(base.ResolveReference(target))

請注意 path 旁的雙斜線。在 Go 1.9 及更早版本中,已解析的 URL 為 http://host/path//to/page2path 之前的雙斜線錯誤地改寫成單一斜線,而 path 之後的雙斜線則正確保留。Go 1.10 保留兩個雙斜線,根據 RFC 3986 的要求,解析成 http://host//path//to/page2

此變更可能會中斷已存在的錯誤程式碼,其無意在路徑中建立開頭為雙斜線的基本 URL,並無意依賴 ResolveReference 來修正此錯誤。例如,若程式碼新增主機前綴,例如 http://host/,至路徑,如 /my/api,會產生一個 URL 包含雙斜線:http://host//my/api

UserInfo 的方法現在將 nil 接收器處理成等價於指向 zero UserInfo 的指標。之前,它們會觸發恐慌。

作業系統

File 新增方法 SetDeadlineSetReadDeadlineSetWriteDeadline,允許在底層檔案描述符支援非封鎖 I/O 作業時設定 I/O 截止時間。這些方法的定義與 net.Conn 中的定義相符。如果 I/O 方法因逾期而失敗,它將傳回逾時錯誤;新的 IsTimeout 函式回報錯誤是否代表逾時。

net.Conn 相符,FileClose 方法保證 Close 回傳後已關閉底層檔案描述符。(在之前的版本中,如果 Close 停止其他 goroutines 中的 I/O,檔案描述符的關閉可能會在 Close 回傳後不久的某個 goroutines 中發生)

在 BSD、macOS 和 Solaris 系統上,Chtimes 現在支援以奈秒精度設定檔案時間(假設底層檔案系統可以表示它們)。

反射

Copy 函式現在允許從字串複製到位元組陣列或位元組切片,以符合 內建 copy 函式

在結構體中,嵌入指向未匯出的結構體類型的指標之前會不正確地回報一個空的 PkgPath 給對應的 StructField,結果是對於那些欄位, Value.CanSet 不正確地回傳 true,且 Value.Set 不正確地成功。底層的元資料已修正;對於那些欄位,CanSet 現在正確回傳 false,且 Set 現在正確地觸發恐慌。這可能會影響依反射為基礎的 unserlializer,在之前可以將資料 unserialize 到此類欄位但現在不行。例如,請參閱 encoding/json 筆記。

執行階段/剖析

如同 上面所述,封鎖和互斥鎖剖析現在包含符號資訊,因此無需不需要產生剖析的二進位檔即可檢視。

字串轉換

ParseUint 現在會回傳大小合適的最大數值整數以及任何 ErrRange 錯誤,正如它在文件中所記載的。之前它會回傳 0 和 ErrRange 錯誤。

字串

新的類型 Builder 可取代 bytes.Buffer 這個用例,將文字累積到 string 結果中。Builder 的 API 是 bytes.Buffer 的限制子集,能在 String 方法中安全避免資料重複複製。

syscall

在 Windows 上,新的 SysProcAttr 欄位 Token,類型是 Token,可在 StartProcess 期間 (因此在 os.StartProcessexec.Cmd.Start 期間也是) 建立一個以其他使用者身分執行的程序。新的函式 CreateProcessAsUser 可以存取基礎系統呼叫。

在 BSD、macOS 和 Solaris 系統上,現在已實作 UtimesNano

time

LoadLocation 現在使用由 $ZONEINFO 環境變數命名的目錄或未壓縮的 zip 檔案,然後才在已知安裝位置的預設系統特定清單或 $GOROOT/lib/time/zoneinfo.zip 中尋找。

新的函式 LoadLocationFromTZData 可將 IANA 時區檔案資料轉換成 Location

unicode

unicode 套件和整個系統中相關支援已從 Unicode 9.0 升級到 Unicode 10.0,新增了 8,518 個新字元,包括四個新文字系統、一個新屬性、一個比特幣貨幣符號和 56 個新表情符號。