Go泛型|青训营笔记

103 阅读3分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第3篇笔记。

美国时间 2022 年 1 月 31 日,在中国人民欢庆虎年春节之际,Go 核心团队发布了Go 1.18 Beta2 版本。在 Go 1.18beta2 版本发布的博文中,Go 核心团队还给出了 Go 1.18 版本的发布计划:2022 年 2 月发布 Go 1.18RC(release candidate,即发布候选版),2022 年 3 月发布 Go 1.18 最终版本。考虑到 Go 1.18 版本中引入了 Go 语言开源以来最大的语法特性变化:泛型(generic),改动和影响都很大,Go 核心团队将 Go 1.18 版本延迟一个月,放到 3 月发布也不失为稳妥之举。在 Go 泛型正式落地之前,我想在这篇加餐中带你认识一下 Go 泛型,目的是“抛砖引玉”,为你后续系统学习和应用 Go 泛型语法特性开个头儿。我们今天将围绕 Go 为什么加入泛型、泛型设计方案的演化历史、Go 泛型的主要语法以及 Go 泛型的使用建议几个方面,聊聊 Go 泛型的那些事儿。首先,我们先来了解一下 Go 语言为什么要加入泛型语法特性。为什么要加入泛型?根据近几年的 Go 官方用户调查结果,在“你最想要的 Go 语言特性”这项调查中,泛型霸榜多年。你可以看下这张摘自最新的2020 年 Go 官方用户调查结果的图片:

image.png 既然 Go 社区对泛型特性的需求如此强烈,那么 Go 核心团队为何要在 Go 开源后的第 13 个年头,才将这个特性加入语言当中呢?这里的故事说来话长。要想了解其中原因,我们需要先来了解一下什么是泛型?维基百科提到:最初泛型编程这个概念来自于缪斯·大卫和斯捷潘诺夫. 亚历山大合著的“泛型编程”一文。那篇文章对泛型编程的诠释是:“泛型编程的中心思想是对具体的、高效的算法进行抽象,以获得通用的算法,然后这些算法可以与不同的数据表示法结合起来,产生各种各样有用的软件”。说白了就是将算法与类型解耦,实现算法更广泛的复用。我们举个简单的例子。这里是一个简单得不能再简单的加法函数,这个函数接受两个 int32 类型参数作为加数: func Add(a, b int32) int32 { return a + b } 不过上面的函数 Add 仅适用于 int32 类型的加数,如果我们要对 int、int64、byte 等类型的加数进行加法运算,我们还需要实现 AddInt、AddInt64、AddByte 等函数。那如果我们用泛型编程的思想来解决这个问题,是怎样呢?我们需要将算法与类型解耦,实现一个泛型版的 Add 算法,我们用 Go 泛型语法实现的泛型版 Add 是这样的(注意这里需要使用 Go 1.18beta1 或后续版本进行编译和运行 func Add[T constraints.Integer](a, b T) T { return a + b } 这样,我们就可以直接使用泛型版 Add 函数去进行各种整型类型的加法运算了