天天看點

曆時 11 年,Go 編譯器終于正式支援泛型!

近日,據外媒報道,Go 項目代碼倉庫在最新送出和合并的一個 PR 中,Go 語言已在 cmd/compile 中預設啟用 -G=3。據描述,該 PR 已将 cmd/compile 的 -G flag 的預設值從 0 改為 3,可使用新 types2 類型檢查器并支援類型參數,正式啟用對泛型的支援。

出于對預設行為變化的考慮(例如,types2 類型檢查器已知的變更),此次 Go編譯器預設啟用 -G=3,正式啟用泛型變更的同時,也更新了回歸測試工具。另外,盡管已預設啟用 -G=3,但目前 -G=0 模式目前仍在測試中。

自 2009 年誕生之後,谷歌開發的程式設計語言 Go 發展至今已有 11 年了。憑借諸多優勢(如比Python更快,比Java更簡潔,有着C++沒有的GC),Go 編譯器一直都深受科技公司開發者或程式設計人員們的青睐。當然近幾年,Go 也越來越多地出現在金融和媒體等行業。

作為一項成功的開源項目,使用 Go 編譯器的人群數量每年都在增長。過去的幾年裡,面對廣泛的 Go 開發者們的的調查顯示,泛型一直被認為是 Go 确實的關鍵。甚至一度從 2010 年讨論至今,其中不乏一些關于 Go 泛型草案的回報和建議。

曆時 11 年,Go 編譯器終于正式支援泛型!

為什麼 Go 語言一直沒有泛型

在此之前,很多人都認為 Go 語言或許永遠都不會加入泛型了。那麼,為什麼 Go 語言到目前為止都一直沒有泛型?如今,Go 編譯器預設啟用 -G=3,正式啟用泛型,那麼“困擾多年”的問題又是如何被解決的呢?

相信對于 Go 語言标準庫了解的朋友,會在如下的代碼中發現有趣的問題:

package sort

func Float64s(a []float64)

func Strings(a []string)

func Ints(a []int)

...

在上述這個以 sort 包提供的函數裡,盡管它們擁有非常相似的底層邏輯和功能,但在傳入類型不同時卻需要對外提供多個函數。這個時候,如果能像 Java 那樣使用泛型的話,就能大大減少重複的代碼和邏輯,也能為程式設計人員提供更強的表達能力,減少工作量的同時還能提升效率。

相關調查資料顯示,由于泛型困境,此前谷歌 Go 程式設計語言開發團隊不得不面臨開發效率、編譯速度和運作速度的選取。與此同時,由于之前 Go 語言方案存在缺陷, Go 團隊也認為泛型的支援不夠緊湊,是以一直沒在 Go 語言前幾個版本中加入泛型。

關于Go語言泛型的發展

一直以來,關于 Go 語言泛型的“推進”工作就一直在進行。

2009 年 11 月 ,Google 正式将Go語言以開放源代碼的形式向全球釋出。第二年,Ian Lance Taylor 就送出了為Go添加泛型的提議,但當時該提議隻是作為示例儲存了起來,并沒有被采納。此後的2012年3月,Go 1 正式釋出,泛型提議再次被提起。

之後幾年裡,由于上述講到的 Go 面臨的“泛型困境”,相關提議也一直在被考慮和在被解決的過程中。一直到 2019 年7月,Ian Lance Taylor 在 Gophercon 2019 上發表關于 “Why Generics?” 的演講時,才正式送出了一份合作泛型設計的草稿。

去年 6 月,這份泛型設計草稿有了更新,才終于被預測能在今年 Go 1.17 版本上見到的可能。

從今年 1 月,Ian Lance Taylor 發起了添加泛型的提案,到 3 月關于泛型提案正式釋出,再到剛剛Go編譯器正式啟用 -G=3 支援泛型,曆時多年,廣大 Go 開發者群體關注的 Go 語言的泛型問題終于得以實作。

最後,避免泛型濫用

時至今日,在語言代碼編譯器的使用過程中,泛型都是極具“進化”性質的一項功能,不僅可以提高開發效率,還能有效幫助開發者減少不必要的重複工作。

但如同任何一門編輯語言一樣,Go 語言的泛型啟用,此後發展過程中的“泛型濫用”也需要值得關注。

相信對于每個程式設計人員來說,在代碼中發現大量被嵌套使用的泛型的時候,都會"如臨大敵”。雖然不似 C++ 那樣标準庫中大量的模闆,但 Go 語言的泛型特征中,也容許使用類型限制,類似 Java 那樣産生“迷”一樣的邏輯,會給代碼編譯效率帶來不少影響。

是以,在引入泛型特征後,Go 語言又将如何處理“函數重命名”邏輯,來幫助有效解決源碼中類型、函數和方法呢?我們将拭目以待。