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