Go 1.17中值得關注的幾個變化

語言: CN / TW / HK

本文永久連結 – https://tonybai.com/2021/08/17/some-changes-in-go-1-17

Go核心開發團隊在 去年GopherCon大會上給Go泛型的定調是在2022年2月份的Go 1.18版本中釋出 ,那可是自 Go誕生 以來語法規範變動最大的一次,這讓包括筆者在內的全世界的Gopher們都滿懷期待。

不過別忘了,在Go 1.18這個“網紅版本”釋出前,還有一個“實力派”版本Go 1.17呢!美國當地時間2021年8月16日, Go 1.17版本在經過兩個RC版本之後正式釋出 !並且值得慶幸的是Go 1.17版本並沒有過多受到Go 1.18版本這個“網紅”的影響,Go 1.17默默地加入和優化了著實不少的特性。在這一篇文章中,我們就來看看Go 1.17版本中有哪些值得關注的變化。

1. 語言特性變化

Go屬於那種極簡的語言 ,從誕生到現在語言自身特性變化很小,不會像其他主流語言那樣走“你有的我也要有”的特性融合路線。因此新語言特性對於Gopher來說屬於“稀缺品”,屬於“供不應求”那類事物^_^。這也直接導致了每次Go新版本釋出,我們都要首先看看語言特性是否有變更,每個新加入語言的特性都值得我們去投入更多關注,去深入研究。Go 1.17在語言特性層面做了兩方面的小改動,下面我們來看看。

第一個是對語言型別轉換規則的擴充套件,允許從切片到陣列指標的轉換,下面的程式碼在Go 1.17版本中是可以正常編譯和執行的:

// github.com/bigwhite/experiments/tree/master/go1.17-examples/lang/slice2arrayptr/main.go
func slice2arrayptr() {
    var b = []int{11, 12, 13}
    var p = (*[3]int)(b)
    p[1] = p[1] + 10
    fmt.Printf("%v\n", b) // [11 22 13]
}

Go通過執行時對這類切片到陣列指標的轉換程式碼做檢查,如果發現越界行為,就會通過執行時panic予以處理。Go執行時實施檢查的一條原則就是“轉換後的陣列長度不能大於原切片的長度”,注意這裡是切片的長度(len),而不是切片的容量(cap)。

第二個變動則是unsafe包增加了兩個函式:Add與Slice。使用這兩個函式可以讓開發人員更容易地寫出符合 unsafe包使用的安全規則 的程式碼。這兩個函式原型如下:

// $GOROOT/src/unsafe.go
func Add(ptr Pointer, len IntegerType) Pointe
func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType

unsafe.Add允許更安全的指標運算,而unsafe.Slice允許更安全地將底層儲存的指標轉換為切片。

2. go module的變化

Go 1.11版本引入go module 以來,每個Go大版本釋出時,go module都會有不少的積極變化,這是Go核心團隊與社群就go module深入互動的結果。

Go 1.17中go module同樣有幾處顯著變化,其中最最重要的一個變化就是pruned module graph(修剪的module依賴圖)。Go 1.17之前的版本某個module的依賴圖由該module的直接依賴以及所有間接依賴組成,無論某個間接依賴是否真正為原module的構建做出貢獻,這樣go命令在解決依賴時會讀取每個依賴的go.mod,包括那些沒有被真正使用到的module,這樣形成的module依賴圖被稱為 完整module依賴圖(complete module graph)

Go 1.17不再使用“完整module依賴圖”,而是引入了pruned module graph(修剪的module依賴圖)。修剪的module依賴圖就是在完整module依賴圖的基礎上將那些“佔著茅坑不拉屎”、對構建完全沒有“貢獻”的間接依賴module修剪後的依賴圖。使用修剪後的module依賴圖進行構建將有助於避免下載或閱讀那些不必要的go.mod檔案,這樣Go命令可以不去獲取那些不相關的依賴關係,從而在日常開發中節省時間。

但module依賴圖修剪也帶來了一個副作用,那就是go.mod檔案size的變大。因為Go 1.17版本後,每次go mod tidy(當go.mod中的go版本為1.17時),go命令都會對main module的依賴做一次深度掃描(deepening scan),並將main module的所有直接和間接依賴都記錄在go.mod中(之前說的版本只記錄直接依賴)。考慮到內容較多,go 1.17將直接依賴和間接依賴分別放在兩個不同的require塊兒中。

3. 編譯器與執行時的變化

Go 1.17增加了對Windows上64位ARM架構的支援,讓開發者可以在更多裝置上原生執行Go。但這個版本編譯器最大的變化是在amd64架構下率先實現了從基於堆疊的呼叫慣例到 基於暫存器的呼叫慣例切換

並且,切換到 基於暫存器的呼叫慣例 後,一組有代表性的Go包和程式的基準測試顯示,Go程式的執行效能提高了約5%,二進位制檔案大小典型減少約2%。也就是說你的Go原始碼使用Go 1.17版本重新編譯一下就能獲得大約5%的效能提升,真希望這樣的優化越多越好!對更多平臺的基於暫存器呼叫慣例的支援將在未來的版本中出現。

除了改為基於暫存器的呼叫慣例之外,Go 1.17編譯器還支援包含 閉包 的函式的內聯(inline)了!這樣一來,一個帶有閉包的函式可能會在函式被內聯的每個地方產生一個不同的閉包程式碼指標,因此,

Go函式的值不能直接比較!

Go編譯器還在Go 1.17中引入了//go:build形式的構建約束指示符,以替代原先易錯的// +build形式。

4. 其他變化

  • 保留龍芯架構GOARCH值

在Go 1.17版本中,Go編譯器保留了中國龍芯cpu架構的GOARCH值 – loong64。關於龍心GOARCH值選用loong64還是loongarch64還有過 一段激烈的爭論 ,最終大多數都贊同的loong64取得了最後的勝利。

  • Go test變化

Go test引入-shuffle的洗牌標誌位,用以控制單元測試或benchmark的執行順序。

另外T和B兩個型別分別都增加了Setenv方法用於在test和benchmark執行期間設定環境變數。

  • time包增加Time物件的GoString形式輸出

我們使用%#v輸出一個Time物件例項時,Go 1.17之前的版本輸出內容如下面:

Go 1.16.5輸出:

time.Time{wall:0xc03f08c0d06c9ed0, ext:83078, loc:(*time.Location)(0x11620e0)}

Go 1.17增加了GoString方法,該方法在Time物件以%#v格式輸出時被自動呼叫,其輸出結果如下:

time.Date(2021, time.August, 17, 20, 29, 42, 58245000, time.Local)

5. 小結

除上述變化之外,Go的其他標準庫隨著新版本的釋出也都會有大量的小改動,但每個開發人員對標準庫的關注點差別很大,因此,在這個系列中不會詳細做說明了,大家還是參考 Go 1.17的釋出說明文件 各取所需吧^_^。

與傳統的“Go新版本值得關注的幾個變化”系列有所不同,本期內容較為簡單和概括,因為更多內容,我將在後續的 Go 1.17新特性詳解系列 中針對上述值得關注的新特性做進一步說明。詳解系列已經寫好,不過首發在了 本人運營的星球“Gopher部落” 上了,如果你迫切想深入瞭解這些新特性,可以加入星球閱讀。

本文所涉及的原始碼可以在 這裡 – https://github.com/bigwhite/experiments/tree/master/go1.17-examples/

“Gopher部落”知識星球 正式轉正(從試運營星球變成了正式星球)!“gopher部落”旨在打造一個精品Go學習和進階社群!高品質首發Go技術文章,“三天”首發閱讀權,每年兩期Go語言發展現狀分析,每天提前1小時閱讀到新鮮的Gopher日報,網課、技術專欄、圖書內容前瞻,六小時內必答保證等滿足你關於Go語言生態的所有需求!部落目前雖小,但持續力很強。在2021年上半年,部落將策劃兩個專題系列分享,並且是部落獨享哦:

  • Go技術書籍的書摘和讀書體會系列
  • Go與eBPF系列

歡迎大家加入!

Go技術專欄“ 改善Go語⾔程式設計質量的50個有效實踐 ”正在慕課網火熱熱銷中!本專欄主要滿足廣大gopher關於Go語言進階的需求,圍繞如何寫出地道且高質量Go程式碼給出50條有效實踐建議,上線後收到一致好評!歡迎大家訂

閱!

我的網課“ Kubernetes實戰:高可用叢集搭建、配置、運維與應用 ”在慕課網熱賣中,歡迎小夥伴們訂閱學習!

我愛發簡訊 :企業級簡訊平臺定製開發專家 https://51smspush.com/。smspush : 可部署在企業內部的定製化簡訊平臺,三網覆蓋,不懼大併發接入,可定製擴充套件; 簡訊內容你來定,不再受約束, 介面豐富,支援長簡訊,簽名可選。2020年4月8日,中國三大電信運營商聯合釋出《5G訊息白皮書》,51簡訊平臺也會全新升級到“51商用訊息平臺”,全面支援5G RCS訊息。

著名雲主機服務廠商DigitalOcean釋出最新的主機計劃,入門級Droplet配置升級為:1 core CPU、1G記憶體、25G高速SSD,價格5$/月。有使用DigitalOcean需求的朋友,可以開啟這個 連結地址 :https://m.do.co/c/bff6eed92687 開啟你的DO主機之路。

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

微信讚賞:

商務合作方式:撰稿、出書、培訓、線上課程、合夥創業、諮詢、廣告合作。

© 2021,bigwhite. 版權所有.