Go 1.16 新功能特性不完全前瞻
Go 1.16 將於 2021 年 2 月釋出。目前已經進入 freeze 狀態,即不再接受新 feature,僅 fix bug、編寫文件和接受安全更新等。
目前 Go 1.16 的釋出說明尚處於早期草稿階段,但 Go 團隊成員正在致力於編寫釋出說明。Go 1.16 的完全特性列表說明還得等真正釋出前才能得到。如今要了解 Go 1.16 功能特性都有哪些變化,只能結合現有的 release note 以及從Go 1.16 里程碑中的 issue 列表中挖掘。
下面就 “挖掘” 到的 Go 1.16 重要功能特性變化做簡要的且不完全的前瞻。
1. 支援 Apple Silicon M1 晶片
Apple Silicon M1 晶片 Macbook 的釋出讓 Go 團隊緊急為 Go 1.16 增加對 M1 的支援。如果要跨平臺編譯,只需設定 GOOS=darwin, GOARCH=arm64 即可構建出可以在搭載 M1 晶片的 Macbook 上執行的 Go 應用。
同時 Go 1.16 還增加了對 ios/amd64 的支援,主要是為了支援在 amd64 架構上的 MacOS 上執行 ios 模擬器。
2. RISC-V 架構支援 cgo 和-buildmode=pie
RISC-V 架構很可能是未來 5-10 年挑戰 ARM 的最主要架構,Go 語言持續加大對 RISC-V 架構的支援,在 Go 1.16 中對 linux/riscv64 又增加了 cgo 支援以及-buildmode=pie。不過目前對 risc-v 仍僅限於 linux os。
3. 有關 go module 的變化
- module-aware 模式成為預設狀態。如要回到 gopath mode,將 GO111MODULE 設定為 auto;
- go build 和 go test 不會修改 go.mod 和 go.sum 檔案。能修改這兩個檔案的命令只有 go get 和 go mod tidy;
- go get 之前的構建和安裝 go 包的行為模式將被廢棄。go get 將專注於分析依賴,並獲取 go 包/module,更新 go.mod/go.sum;
- go install 將恢復自己構建和安裝包的 “角色”(在 go module 加入後,go install 日益受到冷落,這次翻身了);
- go.mod 將支援 retract 指示符,包或 module 作者可以利用該指示符在自己 module 的 go.mod 中標記某些版本撤回 (因不安全、不相容或損壞等原因),不建議使用。
- go.mod 中的 exclude 指示符語義變更:Go 1.16 中將忽略 exclude 指示的 module/包依賴;而之前的版本 go 工具鏈僅僅是跳過 exclude 指示的版本,而使用該依賴包/module 的下一個版本。
- -i build flag 廢棄;
- go get 的-insecure 命令列標誌選項作廢,可以用 GOINSECURE 環境變數指示 go get 是否通過不安全的 http 去獲取包;
4. 支援在 Go 二進位制檔案中嵌入靜態檔案 (文字、圖片等)
Go 1.16 新增go:embed
指示符和 embed 標準庫包,二者一起用於支援在在 Go 二進位制檔案中嵌入靜態檔案。下面是一個在 Go 應用中嵌入文字檔案用於 http 應答內容的小例子:
// hello.txt
hello, go 1.16
// main.go
package main
import (
_ "embed"
"net/http"
)
//go:embed hello.txt
var s string
func main() {
http.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(s))
}))
http.ListenAndServe(":8080", nil)
}
上述原始碼中的go:embed
指示符的含義是:將 hello.txt 內容儲存在字串變數 s 中。我們構建該原始碼,並驗證一下 s 中儲存的是否是 hello.txt 中的資料:
$ go build -o demo main.go
$ mv hello.txt hello.txt.bak // 將hello.txt改名,我們看看資料是否真的已經嵌入到二進位制檔案demo中了
$ ./demo
$curl localhost:8080
hello, go 1.16
5.GODEBUG 環境變數支援跟蹤
當 GODEBUG 環境變數包含 inittrace=1 時,Go 執行時將會報告各個原始碼檔案中的 init 函式的執行時間和記憶體開闢消耗情況。比如對於上面的程式 demo,我們按如下命令執行:
# GODEBUG=inittrace=1 ./demo
init internal/bytealg @0.014 ms, 0 ms clock, 0 bytes, 0 allocs
init runtime @0.033 ms, 0.015 ms clock, 0 bytes, 0 allocs
init errors @0.24 ms, 0.003 ms clock, 0 bytes, 0 allocs
init sync @0.47 ms, 0.001 ms clock, 16 bytes, 1 allocs
init io @0.66 ms, 0 ms clock, 144 bytes, 9 allocs
init internal/oserror @0.85 ms, 0 ms clock, 80 bytes, 5 allocs
init syscall @1.0 ms, 0.006 ms clock, 624 bytes, 2 allocs
init time @1.2 ms, 0.013 ms clock, 384 bytes, 8 allocs
init path @1.4 ms, 0.003 ms clock, 16 bytes, 1 allocs
init io/fs @1.6 ms, 0 ms clock, 16 bytes, 1 allocs
init context @2.3 ms, 0.002 ms clock, 128 bytes, 4 allocs
init math @2.5 ms, 0 ms clock, 0 bytes, 0 allocs
init strconv @2.7 ms, 0 ms clock, 32 bytes, 2 allocs
init unicode @2.9 ms, 0.065 ms clock, 23736 bytes, 26 allocs
init bytes @3.2 ms, 0 ms clock, 48 bytes, 3 allocs
init crypto @3.3 ms, 0.001 ms clock, 160 bytes, 1 allocs
init reflect @3.5 ms, 0.002 ms clock, 0 bytes, 0 allocs
init encoding/binary @3.7 ms, 0 ms clock, 16 bytes, 1 allocs
init crypto/cipher @3.8 ms, 0 ms clock, 16 bytes, 1 allocs
init crypto/aes @4.0 ms, 0.003 ms clock, 16 bytes, 1 allocs
init internal/poll @4.1 ms, 0 ms clock, 64 bytes, 4 allocs
init os @4.2 ms, 0.029 ms clock, 544 bytes, 13 allocs
init fmt @4.4 ms, 0.003 ms clock, 32 bytes, 2 allocs
init math/rand @4.5 ms, 0.023 ms clock, 5440 bytes, 3 allocs
init math/big @4.7 ms, 0.002 ms clock, 32 bytes, 2 allocs
init crypto/sha512 @4.8 ms, 0.004 ms clock, 0 bytes, 0 allocs
init encoding/asn1 @5.0 ms, 0.004 ms clock, 224 bytes, 7 allocs
init vendor/golang.org/x/crypto/cryptobyte @5.1 ms, 0 ms clock, 48 bytes, 2 allocs
init crypto/ecdsa @5.3 ms, 0 ms clock, 48 bytes, 3 allocs
init bufio @5.4 ms, 0.003 ms clock, 176 bytes, 11 allocs
init crypto/rand @5.6 ms, 0.001 ms clock, 120 bytes, 4 allocs
init crypto/rsa @5.7 ms, 0.007 ms clock, 648 bytes, 18 allocs
init crypto/sha1 @5.8 ms, 0 ms clock, 0 bytes, 0 allocs
init crypto/sha256 @5.9 ms, 0 ms clock, 0 bytes, 0 allocs
init encoding/base64 @5.9 ms, 0.006 ms clock, 1408 bytes, 4 allocs
init crypto/md5 @6.0 ms, 0 ms clock, 0 bytes, 0 allocs
init encoding/hex @6.1 ms, 0 ms clock, 16 bytes, 1 allocs
init crypto/x509/pkix @6.1 ms, 0.001 ms clock, 624 bytes, 2 allocs
init path/filepath @6.2 ms, 0 ms clock, 16 bytes, 1 allocs
init vendor/golang.org/x/net/dns/dnsmessage @6.3 ms, 0.009 ms clock, 1616 bytes, 27 allocs
init net @6.3 ms, 0.029 ms clock, 2840 bytes, 74 allocs
init crypto/dsa @6.5 ms, 0 ms clock, 16 bytes, 1 allocs
init crypto/x509 @6.5 ms, 0.016 ms clock, 4768 bytes, 15 allocs
init io/ioutil @6.7 ms, 0.002 ms clock, 16 bytes, 1 allocs
init vendor/golang.org/x/sys/cpu @6.7 ms, 0.009 ms clock, 1280 bytes, 1 allocs
init vendor/golang.org/x/crypto/chacha20poly1305 @6.8 ms, 0 ms clock, 16 bytes, 1 allocs
init vendor/golang.org/x/crypto/curve25519 @6.9 ms, 0 ms clock, 0 bytes, 0 allocs
init crypto/tls @7.0 ms, 0.007 ms clock, 1600 bytes, 11 allocs
init log @7.0 ms, 0 ms clock, 80 bytes, 1 allocs
init mime @7.1 ms, 0.008 ms clock, 1232 bytes, 4 allocs
init mime/multipart @7.2 ms, 0.001 ms clock, 192 bytes, 4 allocs
init compress/flate @7.3 ms, 0.012 ms clock, 4240 bytes, 7 allocs
init hash/crc32 @7.4 ms, 0.014 ms clock, 1024 bytes, 1 allocs
init compress/gzip @7.5 ms, 0 ms clock, 32 bytes, 2 allocs
init vendor/golang.org/x/text/transform @7.5 ms, 0 ms clock, 80 bytes, 5 allocs
init vendor/golang.org/x/text/unicode/bidi @7.6 ms, 0.005 ms clock, 272 bytes, 2 allocs
init vendor/golang.org/x/text/secure/bidirule @7.7 ms, 0.008 ms clock, 16 bytes, 1 allocs
init vendor/golang.org/x/text/unicode/norm @7.8 ms, 0.002 ms clock, 0 bytes, 0 allocs
init vendor/golang.org/x/net/idna @7.8 ms, 0 ms clock, 0 bytes, 0 allocs
init vendor/golang.org/x/net/http/httpguts @7.9 ms, 0.002 ms clock, 848 bytes, 3 allocs
init vendor/golang.org/x/net/http2/hpack @7.9 ms, 0.063 ms clock, 22440 bytes, 32 allocs
init net/http/internal @8.1 ms, 0.005 ms clock, 1808 bytes, 3 allocs
init vendor/golang.org/x/net/http/httpproxy @8.2 ms, 0 ms clock, 336 bytes, 2 allocs
init net/http @8.3 ms, 0.026 ms clock, 10280 bytes, 113 allocs
我們看到各個依賴包中的 init 函式執行的消耗情況都被輸出了出來,根據這些資訊,我們可以很容易判斷出 init 函式中可能存在的效能問題或瓶頸。
6. 連結器進一步優化
既Go 1.15實現了 go linker 的第一階段優化後,Go 1.16 中繼續實施了對 linker 的第二階段優化。優化後的連結器要平均比 Go 1.15 的快 20%-25%,消耗的記憶體卻減少 5%-15%。
7. struct field 的 tag 中的多個 key 可以合併寫
如果某個結構體支援多種編碼格式的序列化和反序列化,比如:json、bson、xml,那麼之前版本需要按如下書寫該結構體的欄位 tag,冗長且重複:
type MyStruct struct {
Field1 string `json:"field_1,omitempty" bson:"field_1,omitempty" xml:"field_1,omitempty" form:"field_1,omitempty" other:"value"`
}
Go 1.16 支援將多個 key 進行合併,上面的 tag 可以寫成如下形式:
type MyStruct struct {
Field1 string `json bson xml form:"field_1,omitempty" other:"value"`
}
8. 其他改變
- 新增 runtime/metrics 包,以替代 runtime.ReadMemStats 和 debug.ReadGCStats 輸出 runtime 的各種度量資料,這個包更通用穩定,效能也更好;
- 新增 io/fs 包,用於提供只讀的操作 os 的檔案樹的高階介面;
- 對 Unicode 標準的支援從 12.0.0 升級為 13.0.0。
附錄:安裝 go tip 版本的兩種方式
1) 從原始碼安裝
$git clone https//github.com/golang/go.git
$cd go/src
$./all.bash
2) 使用 gotip 工具安裝
$go get golang.org/dl/gotip
$gotip download
Go 技術專欄 “改善 Go 語⾔程式設計質量的 50 個有效實踐” 主要滿足廣大 gopher 關於 Go 語言進階的需求,圍繞如何寫出地道且高質量 Go 程式碼給出 50 條有效實踐建議,上線後收到一致好評!78 元簡直就是白菜價,簡直就是白 piao! 歡迎大家訂閱!
我的網課 “Kubernetes 實戰:高可用叢集搭建、配置、運維與應用” 在慕課網熱賣中,歡迎小夥伴們訂閱學習!
“Gopher 部落” 星球首開,福利自然是少不了的!2020 年年底之前,8.8 折加入星球。掃描下方圖片二維碼即享優惠!
Gopher Daily(Gopher 每日新聞) 歸檔倉庫 - https://github.com/bigwhite/gopherdaily
我的聯絡方式:
- 微博:https://weibo.com/bigwhite20xx
- 微信公眾號:iamtonybai
- 部落格:tonybai.com
- github: https://github.com/bigwhite
- “Gopher 部落” 知識星球:https://public.zsxq.com/groups/51284458844544
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- Go 1.16 推出 Embedding FilesGo
- golang1.16新特性速覽Golang
- Go 1.16 中 Module 功能新變化Go
- 前瞻 PHP8.4 的新特性PHP
- OpenSSL支援TLS1.3特性前瞻TLS
- Go 1.16 中關於 go get 和 go install 你需要注意的地方Go
- KoP 2.8.0 新特性前瞻(內附視訊)
- Go 1.16 中值得關注的幾個變化Go
- Redis 7.0 新功能新特性總覽Redis
- TiDB 4.0 新特性前瞻:白話 “悲觀鎖”TiDB
- go-carbon 2.0.0 版本釋出, 要求最低 golang 版本 1.16Golang
- Go 快速指南:go1.18 特性Go
- Go 1.13 新特性Go
- [開源分享]深挖 Linux 核心的新功能特性Linux
- .Net Core3 新特性/新功能 16條
- TiDB 4.0 新特性前瞻(四)圖形化診斷介面TiDB
- Go 1.16 io/fs 設計與實現及正確使用姿勢Go
- 對 Go 1.16 io/fs 設計的第一感覺:得勁兒!Go
- Go 1.12 版本的新特性Go
- 巧萌易攜之ROS2Go的不完全教研攻略ROSGo
- 【Go進階—基礎特性】deferGo
- 【Go進階—基礎特性】介面Go
- 【Go進階—基礎特性】反射Go反射
- 探索 Go1.16 io/fs 包以提高測試效能和可測試性Go
- libiconv-1.16編譯編譯
- SAP HANA 2.0 SP07版本新功能特性彙總
- Go最重要的特性是invisible - JackGo
- 【Go進階—基礎特性】錯誤Go
- Go型別特性-學習筆記Go型別筆記
- 阿里雲訊息佇列 2021 新功能新特性重要里程碑阿里佇列
- PHP8 都有哪些新功能,說說PHP8的新增特性PHP
- TiDB 4.0 新特性前瞻(三)再也不用擔心我的 SQL 突然變慢了TiDBSQL
- Apache Flink 1.16 功能解讀Apache
- Apache Flink 1.16 正式釋出Apache
- 使用 kubeadm 安裝 Kubernetes 1.16
- go-chassis 為 grpc-go 帶來高階雲原生特性GoRPC
- 【Go進階—基礎特性】panic 和 recoverGo
- 【Go進階—基礎特性】定時器Go定時器