Go1.25 新特性:泛型 Core types 將被放棄!
大家好,我是煎魚。
在 Go1.18 版本發(fā)布了泛型,帶來了:類型參數(shù)(type parameters)、類型約束(type constraints)、核心類型(core types)等一大堆泛型帶出來的新概念。引起了一頓新知識的的學(xué)習(xí)浪潮。
圖片
最早泛型 2019 年到現(xiàn)在 2025 年差不多也有個 6 年了。
背景
在 Go1.25 的新特性提前宣發(fā)中,Go 核心團(tuán)隊正式發(fā)布《Goodbye core types - Hello Go as we know and love it![1]》,要將泛型中的核心類型(core types)給干掉。
圖片
要被畢業(yè)的核心類型,又到底是什么呢?
核心類型(Core types)
在 Go 1.18 中,我們引入了 “核心類型[2]”(core type)的概念,以便更容易檢查類型參數(shù)的某些約束。
我們先放例子,我覺得例子比起純理論可能更容易理解。
在 Go 官方的《go spec》中,具體包含核心類型的例子:
type Celsius float32
type Kelvin float32
interface{ int } // int
interface{ Celsius | Kelvin } // float32
interface{ ~chanint } // chan int
interface{ ~chanint | ~chan<- int } // chan<- int
interface {
~[]*data
String() string
} // []*data
注意:右側(cè)注釋就是他所標(biāo)注的核心類型。
不包含核心類型的例子:
interface{} // no single underlying type
interface{ Celsius | float64 } // no single underlying type
interface{ chan int | chan<- string } // channels have different element types
interface{ <-chan int | chan<- int } // directional channels have different directions
核心類型的定義如下:
- 如果某類型 T 的定義是一個類型別名,例如
type T = A
,那么 T 的核心類型就是 A 的核心類型。 - 如果某類型 T 是一個底層類型為某個具體類型的命名類型,那么它的核心類型就是那個底層類型。
- 如果某類型 T 是一個類型參數(shù),并且其約束指定了一個核心類型(比如
~int
或~[]byte
),那么它的核心類型就是那個指定的類型。 - 否則,該類型沒有核心類型。
為什么不要核心類型了?
雖然引入了核心類型試圖統(tǒng)一泛型語義。
結(jié)果卻讓語言規(guī)范更復(fù)雜、學(xué)習(xí)門檻更高、規(guī)則更難一致,發(fā)現(xiàn)最終得不償失。
具體原因如下:
- 核心類型定義不夠靈活,限制過嚴(yán):
比如接口 interface{ ~[]int }
擁有核心類型 []int
,但更復(fù)雜的接口如 Constraint
(即含有方法和多個類型約束的接口)就無法推導(dǎo)出核心類型。
對于 append
、copy
、通道操作等語言特性,核心類型定義過于嚴(yán)格,實際需要對方向、類型組合做額外處理(例如同時包含 []byte
和 string
)。
- 對語言特性理解造成阻礙:
- 某些語言特性(如切片表達(dá)式)在規(guī)范中以“核心類型”為判斷依據(jù),而非更直接地說明“操作數(shù)必須是數(shù)組、切片或字符串”。
- 這讓開發(fā)者即使寫的不是泛型代碼,也得理解 “核心類型” 的概念,徒增學(xué)習(xí)負(fù)擔(dān)。
- 破壞語言規(guī)則的一致性,導(dǎo)致了例外:
- 有些表達(dá)式(如
len
,cap
, 索引表達(dá)式等)并不依賴核心類型判斷,導(dǎo)致語言規(guī)則看起來像是有一堆例外。 - 例如社區(qū)提案 #48522[3] 中提到的 “對聯(lián)合類型元素字段的統(tǒng)一訪問”,如果沒有核心類型這個障礙,其實可以自然落入普通字段訪問規(guī)則中,而不是再新增例外。
Go1.25 會做出什么改變?
由于上述提到的一系列導(dǎo)致 Go 更復(fù)雜的問題,Go 核心團(tuán)隊將決定在 Go1.25(2025 年 8 月)的語言規(guī)范中將核心類型的概念給移除掉。并給未來預(yù)留有需要時將其概念轉(zhuǎn)為顯式的方式。
#go/issues/70128
#go/issues/70128
移除后,將有以下幾個好處:
- 語言規(guī)范更簡潔,易于學(xué)習(xí):
Go 規(guī)范呈現(xiàn)的概念更少,不再引入“核心類型”這種額外抽象。
初學(xué)者能更快理解語言的核心結(jié)構(gòu),不被泛型細(xì)節(jié)干擾。
- 非泛型代碼無需了解泛型語義:
- 你寫的是普通代碼,就不需要去理解類型參數(shù)、類型約束或核心類型。
- 泛型不再“污染”對普通語言特性的理解,使 Go 保持其一貫的簡潔直觀。
- 針對具體操作采用具體規(guī)則,更具靈活性:
- 用 “具體規(guī)則匹配具體操作” 而非 “一刀切” 的抽象模型,為語言擴展打開了大門。
- 不僅讓 issue #48522(字段選擇器適用于類型集合)更自然,也為將來支持更強大的切片操作、更智能的類型推導(dǎo)等功能提供空間。
總結(jié)
Go 泛型雖然已經(jīng)發(fā)布了 6 年,但目前仍然在持續(xù)的迭代過程中。在以往包含核心類型的概念時,泛型確實有一定的學(xué)習(xí)成本。
在后續(xù)的 Go1.25 新版本移除后,雖然有所降低。但是感覺泛型的更好的成熟可用還是有一定的發(fā)展空間的。
參考資料
[1] Goodbye core types - Hello Go as we know and love it!: https://go.dev/blog/coretypes
[2] 核心類型: https://go.dev/ref/spec#Core_types
[3] #48522: https://go.dev/issue/48522