Go1.25 新特性:泛型 Core types 将被放弃!

开发 前端
在 Go1.18 版本发布了泛型,带来了:类型参数(type parameters)、类型约束(type constraints)、核心类型(core types)等一大堆泛型带出来的新概念。引起了一顿新知识的的学习浪潮。

大家好,我是煎鱼。

在 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
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

注意:右侧注释就是他所标注的核心类型。

不包含核心类型的例子:

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.
  • 2.
  • 3.
  • 4.

核心类型的定义如下:

  • 如果某类型 T 的定义是一个类型别名,例如 type T = A,那么 T 的核心类型就是 A 的核心类型。
  • 如果某类型 T 是一个底层类型为某个具体类型的命名类型,那么它的核心类型就是那个底层类型。
  • 如果某类型 T 是一个类型参数,并且其约束指定了一个核心类型(比如 ~int 或 ~[]byte),那么它的核心类型就是那个指定的类型。
  • 否则,该类型没有核心类型。

为什么不要核心类型了?

虽然引入了核心类型试图统一泛型语义。

结果却让语言规范更复杂、学习门槛更高、规则更难一致,发现最终得不偿失。

具体原因如下:

  • 核心类型定义不够灵活,限制过严

比如接口 interface{ ~[]int } 拥有核心类型 []int,但更复杂的接口如 Constraint(即含有方法和多个类型约束的接口)就无法推导出核心类型。

对于 appendcopy、通道操作等语言特性,核心类型定义过于严格,实际需要对方向、类型组合做额外处理(例如同时包含 []byte 和 string)。

  • 对语言特性理解造成阻碍:
  • 某些语言特性(如切片表达式)在规范中以“核心类型”为判断依据,而非更直接地说明“操作数必须是数组、切片或字符串”。
  • 这让开发者即使写的不是泛型代码,也得理解 “核心类型” 的概念,徒增学习负担。
  • 破坏语言规则的一致性,导致了例外:
  • 有些表达式(如 lencap, 索引表达式等)并不依赖核心类型判断,导致语言规则看起来像是有一堆例外。
  • 例如社区提案 #48522[3] 中提到的 “对联合类型元素字段的统一访问”,如果没有核心类型这个障碍,其实可以自然落入普通字段访问规则中,而不是再新增例外。

Go1.25 会做出什么改变?

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

#go/issues/70128#go/issues/70128

#go/issues/70128

移除后,将有以下几个好处:

  • 语言规范更简洁,易于学习

Go 规范呈现的概念更少,不再引入“核心类型”这种额外抽象。

初学者能更快理解语言的核心结构,不被泛型细节干扰。

  • 非泛型代码无需了解泛型语义
  • 你写的是普通代码,就不需要去理解类型参数、类型约束或核心类型。
  • 泛型不再“污染”对普通语言特性的理解,使 Go 保持其一贯的简洁直观。
  • 针对具体操作采用具体规则,更具灵活性
  • 用 “具体规则匹配具体操作” 而非 “一刀切” 的抽象模型,为语言扩展打开了大门。
  • 不仅让 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

责任编辑:武晓燕 来源: 脑子进煎鱼了
相关推荐

2025-02-08 11:00:33

2021-09-29 18:17:30

Go泛型语言

2021-01-14 05:20:48

Go语言泛型

2024-12-30 11:05:28

泛型Go类型别名

2021-12-13 08:52:42

Go 泛型

2021-08-09 10:36:20

GoSlices Maps

2024-10-28 00:40:49

Go语法版本

2014-04-15 16:01:00

Java8泛型

2022-03-28 13:34:26

Go泛型部署泛型

2021-11-27 22:20:13

SlicesGo泛型

2023-11-03 14:02:04

Go切片泛型库

2023-11-29 08:19:45

Go泛型缺陷

2009-09-09 14:11:58

Scala泛型

2021-09-05 18:25:30

Go命令仓库

2023-08-09 08:53:50

GoWASI语义

2021-12-05 23:45:23

Go泛型Maps

2021-12-15 10:23:56

Go 1.18 Bet语言泛型

2022-04-15 09:55:59

Go 泛型Go 程序函数

2024-01-22 00:30:00

Go编程Go 1.22

2019-12-09 10:02:41

泛型ypeScript前端
点赞
收藏

51CTO技术栈公众号