• Go1.25 新特性:泛型 Core types 将被放弃!
  • 发布于 1周前
  • 56 热度
    0 评论
在 Go1.18 版本发布了泛型,带来了:类型参数(type parameters)、类型约束(type constraints)、核心类型(core types)等一大堆泛型带出来的新概念。引起了一顿新知识的的学习浪潮。最早泛型 2019 年到现在 2025 年差不多也有个 6 年了。

背景
在 Go1.25 的新特性提前宣发中,Go 核心团队正式发布《Goodbye core types - Hello Go as we know and love it![1]》,要将泛型中的核心类型(core types)给干掉。

要被毕业的核心类型,又到底是什么呢?

核心类型(Core types)
在 Go 1.18 中,我们引入了 “核心类型[2]”(core type)的概念,以便更容易检查类型参数的某些约束。我们先放例子,我觉得例子比起纯理论可能更容易理解。在 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
注意:右侧注释就是他所标注的核心类型。
不包含核心类型的例子:
 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
核心类型的定义如下:
1.如果某类型 T 的定义是一个类型别名,例如 type T = A,那么 T 的核心类型就是 A 的核心类型。
2.如果某类型 T 是一个底层类型为某个具体类型的命名类型,那么它的核心类型就是那个底层类型。
3.如果某类型 T 是一个类型参数,并且其约束指定了一个核心类型(比如 ~int 或 ~[]byte),那么它的核心类型就是那个指定的类型。

4.否则,该类型没有核心类型。


为什么不要核心类型了?
虽然引入了核心类型试图统一泛型语义。结果却让语言规范更复杂、学习门槛更高、规则更难一致,发现最终得不偿失。
具体原因如下:
1.核心类型定义不够灵活,限制过严:
比如接口 interface{ ~[]int } 拥有核心类型 []int,但更复杂的接口如 Constraint(即含有方法和多个类型约束的接口)就无法推导出核心类型。
对于 append、copy、通道操作等语言特性,核心类型定义过于严格,实际需要对方向、类型组合做额外处理(例如同时包含 []byte 和 string)。
2.对语言特性理解造成阻碍:
某些语言特性(如切片表达式)在规范中以“核心类型”为判断依据,而非更直接地说明“操作数必须是数组、切片或字符串”。
这让开发者即使写的不是泛型代码,也得理解 “核心类型” 的概念,徒增学习负担。
3.破坏语言规则的一致性,导致了例外:
有些表达式(如 len, cap, 索引表达式等)并不依赖核心类型判断,导致语言规则看起来像是有一堆例外。

例如社区提案 #48522[3] 中提到的 “对联合类型元素字段的统一访问”,如果没有核心类型这个障碍,其实可以自然落入普通字段访问规则中,而不是再新增例外。


Go1.25 会做出什么改变?
由于上述提到的一系列导致 Go 更复杂的问题,Go 核心团队将决定在 Go1.25(2025 年 8 月)的语言规范中将核心类型的概念给移除掉。并给未来预留有需要时将其概念转为显式的方式。

移除后,将有以下几个好处:
1.语言规范更简洁,易于学习:
.Go 规范呈现的概念更少,不再引入“核心类型”这种额外抽象。
.初学者能更快理解语言的核心结构,不被泛型细节干扰。
2.非泛型代码无需了解泛型语义:
.你写的是普通代码,就不需要去理解类型参数、类型约束或核心类型。
.泛型不再“污染”对普通语言特性的理解,使 Go 保持其一贯的简洁直观。
3.针对具体操作采用具体规则,更具灵活性:
.用 “具体规则匹配具体操作” 而非 “一刀切” 的抽象模型,为语言扩展打开了大门。

.不仅让 issue #48522(字段选择器适用于类型集合)更自然,也为将来支持更强大的切片操作、更智能的类型推导等功能提供空间。


总结
Go 泛型虽然已经发布了 6 年,但目前仍然在持续的迭代过程中。在以往包含核心类型的概念时,泛型确实有一定的学习成本。在后续的 Go1.25 新版本移除后,虽然有所降低。但是感觉泛型的更好的成熟可用还是有一定的发展空间的。

参考资料
[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

用户评论