關(guān)于 Go 語(yǔ)言泛型設(shè)計(jì)的最新進(jìn)展和一些問(wèn)題的說(shuō)明
前段時(shí)間 Go 官方發(fā)布了新的泛型草案,一時(shí)間在社區(qū)引起了很大的反響,各種關(guān)于泛型的文章、討論涌現(xiàn)出來(lái)。8 月 21日 Ian Lance Taylor 在 golang-nuts[1] 討論組總結(jié)了泛型設(shè)計(jì)的最新進(jìn)展和一些問(wèn)題的說(shuō)明。
Go Team 在經(jīng)過(guò)多次討論并閱讀了許多評(píng)論后,計(jì)劃對(duì)泛型設(shè)計(jì)進(jìn)行一些更改并澄清草案的一些問(wèn)題。
1
泛型語(yǔ)法極有可能使用方括號(hào) [](不用 <> 是因?yàn)楹捅容^運(yùn)算符大于、小于沖突,為了保持 Go1 兼容性,所以選擇了 []),但考慮刪除類型參數(shù)中的 type 關(guān)鍵字,因?yàn)槭褂梅嚼ㄌ?hào)足以區(qū)分類型參數(shù)和普通參數(shù)。為了避免與數(shù)組聲明混淆,將要求所有類型參數(shù)都提供一個(gè)約束(constraint)。這樣做的好處是可以給類型參數(shù)列表與普通參數(shù)列表使用完全相同的語(yǔ)法(除了括號(hào)的區(qū)別之外)。為簡(jiǎn)化類型參數(shù)的常見(jiàn)情況,該參數(shù)可以無(wú)限制,將引入一個(gè)新的預(yù)先聲明的標(biāo)識(shí)符 any 作為 interface{} 的別名。
所以支持泛型的聲明類似這樣:
type?Vector[T?any]?[]T?
func?Print[T?any](s?[]T?"T?any")?{?…?}?
func?Index[T?comparable](s?[]T,?e?T?"T?comparable")?{?…?}?
Go Team 認(rèn)為預(yù)定義新標(biāo)識(shí)符 any 的成本較低:因?yàn)槊總€(gè)常規(guī)參數(shù)始終都有一個(gè)類型,每個(gè)類型參數(shù)始終具有一個(gè)約束(其元類型)。
將 [type T] 更改為 [T any] 似乎同樣易讀,并且節(jié)省了一個(gè)字符。我們將能夠簡(jiǎn)化許多現(xiàn)有的標(biāo)準(zhǔn)庫(kù)和其他地方的代碼,只需替換 interface {} 為 any 即可。
2
將簡(jiǎn)化類型列表滿足的規(guī)則。如果類型參數(shù)或者類型參數(shù)的底層(underlying )類型和類型列表中的任意類型相同,則類型參數(shù)滿足約定。調(diào)整后的規(guī)則意味著,類型列表可以決定是否接受除預(yù)先聲明的類型外的確切定義的類型,或者是否接受具有匹配底層類型的任何類型。
這是一個(gè)微小的變化,預(yù)計(jì)不會(huì)影響任何現(xiàn)有的實(shí)驗(yàn)代碼。
3
需要澄清的是,在考慮允許的操作時(shí),對(duì)于類型參數(shù)中某個(gè)類型的值,將忽略在類型列表中的任何類型方法。一般規(guī)則是,泛型函數(shù)可以使用類型中每種類型允許的任何操作清單。但是,這僅適用于自定義函數(shù)和預(yù)聲明的函數(shù)(例如 len 和 cap)。它不適用于方法,因?yàn)轭愋土斜戆卸x了方法的類型列表。任何方法都必須在 interface 中單獨(dú)列出,而不是從類型列表中繼承。即泛型函數(shù)只能使用類型約束所定義的那些操作。
該規(guī)則通常看起來(lái)很清晰,并且避免了一些復(fù)雜的推理涉及類型列表,其中包括帶有嵌入式類型的結(jié)構(gòu)參數(shù)。
4
允許對(duì)具有類型列表的類型參數(shù)執(zhí)行類型開(kāi)關(guān)(type switch)操作。用 (.type) 的語(yǔ)法來(lái)闡明類似 switch v := x.(type) 的代碼。在類型參數(shù)上的類型開(kāi)關(guān)不能使用 := 語(yǔ)法,因此 .(type) 是不必要的。在具有類型列表的類型參數(shù)上執(zhí)行類型開(kāi)關(guān)操作時(shí),列出的每一個(gè) case 都必須是出現(xiàn)在類型列表中的(當(dāng)然也允許使用 default)。如果和類型參數(shù)匹配,則該 case 被選中。如上面討論的那樣,可能該 case 不是完全匹配的類型參數(shù)而是類型參數(shù)的底層類型,該 case 也會(huì)被選中。
為了使該規(guī)則更明確。沒(méi)有類型列表的類型參數(shù)不允許使用類型開(kāi)關(guān)。但這種情況是允許的:對(duì)于一個(gè)沒(méi)有類型列表的類型參數(shù)值 x,可以寫這樣的代碼,switch (interface{})(x).(type),根據(jù)上面的說(shuō)明,以后應(yīng)該寫成這樣 switch any(x).(type)。這個(gè)結(jié)構(gòu)不是最簡(jiǎn)單的,但它僅使用了語(yǔ)言已有的特性。
接下來(lái)
這些更改將很快在以下實(shí)驗(yàn)設(shè)計(jì)中實(shí)現(xiàn):dev.generics 分支,并在 go2go Playground 可用。以上有些已經(jīng)可以完成了。同時(shí) Go Team 會(huì)相應(yīng)地更新設(shè)計(jì)草案。
參考資料
golang-nuts: https://groups.google.com/g/golang-nuts/c/iAD0NBz3DYw/m/VcXSK55XAwAJ
覺(jué)得不錯(cuò),歡迎關(guān)注:
點(diǎn)個(gè)贊、在看和轉(zhuǎn)發(fā)是最大的支持
