Go 博客

泛型的下一步

Ian Lance Taylor 和 Robert Griesemer
2020 年 6 月 16 日

引言

距离我们 上次撰写关于在 Go 中添加泛型的可能性的文章已经将近一年了。现在是时候进行一次更新了。

更新的设计

我们一直在持续改进 泛型设计草案。我们为此编写了一个类型检查器:一个可以解析如设计草案所述使用泛型的 Go 代码并报告任何类型错误的程序。我们编写了示例代码。并且我们收集了许多许多人的反馈——感谢你们的提供!

基于我们的学习,我们发布了一个更新的设计草案。最大的变化是我们放弃了“契约”(contracts)的概念。契约和接口类型之间的区别令人困惑,所以我们消除了这种区别。类型参数现在由接口类型约束。接口类型现在允许包含类型列表,但仅当它们用作约束时;在先前设计草案中,类型列表是契约的一个特性。更复杂的情况将使用参数化接口类型。

我们希望人们会发现这个设计草案更简单、更容易理解。

实验工具

为了帮助决定如何进一步完善设计草案,我们发布了一个翻译工具。这个工具允许人们对使用设计草案中所描述的泛型版本的代码进行类型检查和运行。它通过将泛型代码翻译成普通 Go 代码来实现。这个翻译过程会施加一些限制,但我们希望它足以让人们感受一下泛型 Go 代码可能是什么样子。如果泛型被接受到语言中,实际的实现将有所不同。(我们才刚刚开始勾勒出直接的编译器实现会是什么样子。)

该工具可在 Go playground 的一个变体版本上使用,网址是 https://go2goplay.golang.org。这个 playground 工作方式与普通的 Go playground 类似,但它支持泛型代码。

你也可以自己构建和使用该工具。它在 Go 主仓库的一个分支中可用。请遵循 从源代码安装 Go 的说明。在那些指示你检出最新发布标签的地方,请改为运行 git checkout dev.go2go。然后按照指示构建 Go 工具链。

翻译工具在 README.go2go 中有文档说明。

下一步

我们希望该工具能让 Go 社区有机会试验泛型。我们希望学习到的主要有两点。

首先,泛型代码有意义吗?它感觉像 Go 吗?人们会遇到什么意外?错误消息有用吗?

其次,我们知道许多人说过 Go 需要泛型,但我们不一定确切地知道这意味着什么。这个草案设计是否以一种有用的方式解决了问题?如果你遇到的问题让你觉得“如果 Go 有泛型,我可以解决它”,那么在使用这个工具时,你能解决这个问题吗?

我们将使用从 Go 社区收集到的反馈来决定如何前进。如果设计草案受到好评且不需要重大更改,下一步将是正式的语言变更提案。为了设定预期,如果每个人都对设计草案完全满意且不需要任何进一步的调整,最早将泛型添加到 Go 的时间将是 2021 年 8 月发布的 Go 1.17 版本。实际上,当然,可能会有未预见的困难,所以这是一个乐观的时间表;我们无法做出任何明确的预测。

反馈

提供语言变更反馈的最佳方式是使用邮件列表 golang-nuts@googlegroups.com。邮件列表不完美,但似乎是我们初步讨论的最佳选择。在撰写关于设计草案的内容时,请在主题行开头加上 [generics],并为不同的特定主题开启不同的主题帖。

如果你在泛型类型检查器或翻译工具中发现 bug,应在标准的 Go 问题跟踪器 go.dev/issue 中提交。请在问题标题开头加上 cmd/go2go:。请注意,问题跟踪器不是讨论语言变更的最佳场所,因为它不提供线程功能,也不适合进行冗长的讨论。

我们期待您的反馈。

致谢

我们还没有完成,但已经取得了长足的进步。如果没有许多人的帮助,我们不会走到今天这一步。

我们要感谢 Philip Wadler 和他的合作者对 Go 泛型进行了正式思考,并帮助我们理清了设计的理论方面。他们的论文 Featherweight Go 分析了一个受限版本的 Go 中的泛型,并且他们在 GitHub 上开发了一个原型。

我们还要感谢那些人,他们对设计草案的早期版本提供了详细的反馈。

最后但同样重要的是,我们要感谢 Go 团队中的许多人,Go 问题跟踪器的许多贡献者,以及所有在早期设计草案中分享想法和反馈的其他人。我们阅读了所有内容,并且心存感激。没有你们,我们不会走到今天这一步。

下一篇文章:保持模块的兼容性
上一篇文章:Pkg.go.dev 开源了!
博客索引