Go 泛型有沒(méi)有可能在后期改為 <> 尖括號(hào)?
大家好,我是煎魚。
最近有一個(gè)社區(qū)朋友反饋他在某乎上看到一個(gè)提問(wèn),內(nèi)容是如標(biāo)題,對(duì)于 Go 泛型的標(biāo)識(shí)符 <> 不太滿意,想看看 Go 以后有沒(méi)有機(jī)會(huì)改。
問(wèn)題上的原話是:
一直對(duì) Go 語(yǔ)言的泛型使用 [] 中括號(hào)耿耿于懷,[] 中括號(hào)在視覺(jué)上很難有辨識(shí)度,尤其是和切片在視覺(jué)上不具有明顯區(qū)別,當(dāng)泛型類型約束是切片時(shí)更是災(zāi)難,對(duì)此一直久久不能釋懷,那么 Go 官方在后續(xù)版本迭代中是否會(huì)考慮新增 <> 來(lái)表示泛型,也就是說(shuō) [] 和 <> 都能表示泛型,由開(kāi)發(fā)者自己決定采用哪個(gè)。
考慮到以前的很多同學(xué)沒(méi)了解過(guò) Go 設(shè)計(jì)的歷史,我又翻了出來(lái)。
快速溫習(xí)
針對(duì)泛型而言,我們做一個(gè)快速的溫習(xí)。泛型允許程序員在強(qiáng)類型語(yǔ)言中編寫代碼時(shí),使用一些以后才確定的類型,其在真正實(shí)例化時(shí)才會(huì)為這些參數(shù)指確定類型。
簡(jiǎn)單來(lái)講,泛型就是參數(shù)化多態(tài)。其可根據(jù)實(shí)參類型生成不同的版本,支持任意數(shù)量的調(diào)用:
func F(a, b T) T{ return a+b }
// T 為 int
F(1, 2)
// T 為 string
F("1", "2")在編譯時(shí)期編譯器便確定其 T 的入?yún)㈩愋汀?/p>
為什么不使用尖括號(hào)
很多同學(xué)在討論的一個(gè)問(wèn)題,那就是 “為什么 Go 泛型不像 C++ 和 Java 那樣使用尖括號(hào)?,也出現(xiàn)了 “Go 一直標(biāo)榜業(yè)界工程實(shí)踐類的榜樣,為什么就是不用尖括號(hào)” 的言論?
思考問(wèn)題我們不只看表面,官方說(shuō)不行,那么我們可以倒推來(lái)看,看看 Go 語(yǔ)言就用尖括號(hào):
func print<type T>(list []T) {
print<int>(numbers)
print<string>(strings)
print<float64>(floats)普通的函數(shù)聲明看上去似乎結(jié)構(gòu)清晰,沒(méi)有什么大問(wèn)題的。接著往下看:
a := w < x
b := y > (z)我們繼續(xù)把代碼演進(jìn)一下,簡(jiǎn)潔一點(diǎn):
a, b := w < x, y > (z)這時(shí)候就犯難了,不僅編譯器難以解析,人也很難判別,到底指的是:
a := w < x
b := y > (z)又或是:
a, b := w<x, y>(z)從上述代碼來(lái)看,使用尖括號(hào)難以分別,因?yàn)闆](méi)有類型信息,就無(wú)法確定賦值的右側(cè)是一對(duì)表達(dá)式 w < x 和 y > (z),還是返回兩個(gè)結(jié)果值 w<x, y>(z) 的泛型函數(shù)實(shí)例化和調(diào)用,其存在歧義。
如果要解決還要引入新的約束,可能會(huì)破壞 Go1 的兼容性承諾,這顯然是違反 Go 的規(guī)范的,在這屆核心團(tuán)隊(duì)中是無(wú)法推進(jìn)的。
為什么不使用括號(hào)
其實(shí)最早 Go 泛型的版本是使用了括號(hào)的模式,雖然能用,但是用括號(hào)會(huì)引入新的解析歧義。例如:
var f func(x(T))從語(yǔ)法上來(lái)講,你無(wú)法識(shí)別他是未命名參數(shù)的 x(T) 函數(shù),還是類型名為參數(shù)的 (T) 函數(shù)。
同時(shí) Go 語(yǔ)言還存在強(qiáng)制類型轉(zhuǎn)換這一語(yǔ)法,假設(shè)代碼是 []T(v1) 和 []T(v2){} ,那么你在開(kāi)括號(hào)處,就無(wú)法得知其是否代表類型轉(zhuǎn)換。
甚至在函數(shù)的完整聲明上,我們都會(huì)感到困惑:
func F(T any)(v T)(r1, r2 T)函數(shù)入?yún)ⅰ⒎盒?、返回值聲明均都是括?hào),造成了語(yǔ)義不清,這顯然也是不合理的。
為什么不使用書名號(hào)
書名號(hào),也就是:??。Go 核心團(tuán)隊(duì)表示過(guò),不想使用非 ASCII,未來(lái)更沒(méi)打算支持這類情況。
一些爭(zhēng)議
網(wǎng)上也有社區(qū)里的同學(xué)對(duì)不支持 Go 官方的尖括號(hào) <> 的說(shuō)法不是很認(rèn)可。
例如,前面提到的 Go 里泛型用尖括號(hào)會(huì)沖突的這個(gè)寫法:
v1,v2 := a<b,c>dGo 核心團(tuán)隊(duì)表示說(shuō)比較為難。
但網(wǎng)友 @Ninsun 同樣甩出了 C++ 泛型的用法下是 OK 的。如下圖:

因此有許多社區(qū)同學(xué)表示,Go 不想用尖括號(hào)就是懶得處理,嫌編譯器 parser 不好寫。
總結(jié)
現(xiàn)在來(lái)看 Go 已經(jīng)不太可能在后期將泛型改為 <> 尖括號(hào)了。畢竟,米已成炊。泛型也已經(jīng)有了定論好幾年了,尖括號(hào)早已被否決。
另外 Go 核心團(tuán)隊(duì)顯然不希望使用尖括號(hào)寫法,這樣會(huì)造成明確語(yǔ)義沖突,也不希望花費(fèi)大量功夫去重新調(diào)整編譯器。
還剩唯一一種可能性,那就是 Go 核心團(tuán)隊(duì)大換血...(難)

























