長達 12 年,Go 泛型才引入,是政治,還是技術問題?

煎魚發表於2021-12-22

大家好,我是煎魚。

前兩天 Go1.18 beta1 已經發布,距離正式釋出 Go1.18 的生產可用還有 2 個月,也就是泛型即將正式面世。

最近正在收集泛型的一些資料,看到在 2015 年有人在 Hacker News 上的《Go 1.5 max procs default》吐槽 Go 不支援泛型是 “政治” 原因...

看了還是有些意義的,與現在的矛盾點基本一致,為此分享給大家。

網友吐槽

網友 @aikah 認為 Go 團隊不太可能在語言中加入泛型,這顯然是一個政治問題而不是技術問題。錯誤處理也是如此。

和許多人一樣,該網友認為 Go 在極簡主義和功能之間沒有取得正確的平衡。反對泛型的人贊成用編譯時型別檢查(總是安全的)換取執行時型別斷言(可能失敗)。

他們拒絕承認這一事實。這就是他們反對泛型的論點,並將最終損害語言的任何潛在增長。他們基本上是在違背自己的利益。

官方回覆

Russ Cox 做了正式的回覆:很抱歉,但不是:泛型是一個技術問題,不是一個政治問題。

Go 團隊並不反對泛型本身,只是反對做那些沒有被很好理解或不能很好地與 Go 配合的事情。

這就是核心觀點和矛盾點,也從 2009 年,延續到了現在。

會遇到的問題

Go 團隊認為要將泛型的概念融入 Go,並與系統的其他部分很好地配合,必須解決一些深層次的技術問題,而我們並沒有解決這些問題的辦法。

關於這些問題,在幾年前就在部落格上寫過一篇《The Generic Dilemma》:

即使克服了那一頁上的問題,也有其他問題,接下來你會遇到的問題是:”如何讓程式設計師以一種有用的、易於解釋的方式省略型別註釋“。

也就是如何更人性、更易於的表達泛型的型別引數。

泛型例子

舉個例子,C++ 允許你寫 make_pair(1, "foo"),而不是 make_pair<int, string>(1, "foo")

為了達到這種效果,推斷註釋背後的邏輯需要幾頁幾頁的規範,這並不是一個特別容易理解的程式設計模型,當事情出錯時,編譯器也不能輕易解釋。

在這之後肯定還有更多的新問題在這裡面。

和專家溝通

Go 團隊和一些真正的 Java 泛型專家談過,他們每個人都說了大致相同的話:要非常小心,它不像看起來那麼容易,而且你會被你犯的所有錯誤困住。

作為一個 Java 示範,可以瀏覽一下《Java Generics FAQs - Frequently Asked Questions》的大部分內容:

看看過了多久你會開始思考 "這真的是最好的方法嗎?"。

在泛型過程中會遇到許多問題,像是《How do I decrypt Enum<E extends Enum<E>>》:

為此,Go 團隊在泛型的推動上非常謹慎。

承認缺點

Go 團隊說得很清楚,承認這個事實:沒有泛型是有一定的缺點的

你要麼使用 interface{} 而放棄編譯時檢查,要麼寫程式碼生成器而使你的構建過程複雜化。

現有語言中實現的泛型也有明確的缺點,而且今天不妥協有一個非常大的好處:它使明天採用更好的解決方案變得更加容易

總結

今天給大家分享了過去在國外社群針對 Go 泛型的各種爭議和探討,其實泛型的核心觀點很明確:”Go 團隊不反對泛型本身“。

一直沒能把泛型做起來,也是因為顧慮很多,做泛型要和 Go 多個部分,要解決很多深層次的問題,還要解決型別引數可讀性等問題。所以一直拖到了現在。

回到即將 2022 年的現在,都預言對了。社群都在扯做泛型後的多個關聯元件,以及泛型可讀性和結構...

顯然,泛型就是雙刃劍?你怎麼看

若有任何疑問歡迎評論區反饋和交流,最好的關係是互相成就,各位的點贊就是煎魚創作的最大動力,感謝支援。

文章持續更新,可以微信搜【腦子進煎魚了】閱讀,本文 GitHub github.com/eddycjy/blog 已收錄,學習 Go 語言可以看 Go 學習地圖和路線,歡迎 Star 催更。

相關文章