Go 泛型變更:約束太醜了,先移動到 x/exp 做實驗性功能

煎魚發表於2022-02-07

大家好,我是煎魚。

Go 泛型配套了各種標準庫,像是常見的 maps、slices 泛型庫。

早期他們是長這樣的:

package maps

func Keys[M constraints.Map[K, V], K comparable, V any](m M) []K

func Values[M constraints.Map[K, V], K comparable, V any](m M) []V
...

又或是:

package slices

func Compare[E constraints.Ordered](s1, s2 []E) int 
...

關注到裡面的標準庫 constraints,他就是今天變更的主角。他咋了呢?

背景

標準庫 constraints 是個新鮮事物,由泛型扛把子 Ian Lance Taylor 在 2021 年 9 月 24 日提交《constraints: new package to define standard type parameter constraints》 所新增。

如下圖:

主要作用是新增一個約束(constraints)包來定義一些標準有用的約束,所以我們會在通用庫看到這些標準約束的使用。

緣由

新提案

在社群一番熱烈討論中,有人提了一個提案《proposal: constraints: rename package to "of"》,希望對 constraints 包進行更名。

新的程式碼如下:

func Abs[V of.Number](v V) V{...}

func Sum[K comparable, V of.Number](m map[K]V) V {...}

作者認為使用 “of” 這個關鍵字比 “constraints” 更簡單流暢。

該提案引來了大量的討論,覺得 constraints 這個名字現在太長,一旦函式簽名比較多,就會很繁瑣,看著也不舒服。

有建議使用引用別名來解決的:

import of “constraints”

也有說是用 any,is 名字,甚至叫 std,或是其他的匯入方式。

眾說紛紜,雖然在後面大幅度的優化了 constraints 的使用頻率,但一旦用到 2~3 次,就會出現函式簽名過於龐大的問題。

最終由於未能討論出明確的共識,被拒絕。

掙扎的結論

經過這長時間的泛型推進和命名爭議,Russ Cox 發現約束包仍然存在著許多問題,是待商榷的。

分別是:

  • 包名字太醜:很多人對包的名字,也就是對 constraints 很滿意,也有很不滿意的,覺得太長,太囉嗦。
  • 不知道放什麼:對於放在包裡面的東西,尚不清楚哪些介面是重要的,應該存在,哪些不應該存在。
  • 似乎不需要:一開始認為標準的約束是使用泛型的基礎,但在實踐中並沒有證明是這樣,甚至可以不要。

基於上述原因,Go 團隊決定將標準庫 constraints 與 maps、slices 一樣,轉移到 x/exp 中,作為實驗性功能來對待。

再在 Go 1.19 或 1.20 中重新審視他們,看看是不是真的有用,又或是怎麼用才是對的,再做決定。

總結

Go 泛型在本月(2月)即將在 Go1.18 中釋出(春節的時候,通知社群鴿到 3 月份了...),雖然從表面來看,核心功能已經基本定型了,但配套設施還是比較亂。

建議大家在正式生產使用上,還是有注意節奏,免得踩坑。

你覺得 constraints 這個命名咋樣,歡迎大家一起來討論:)

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

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

參考

相關文章