Go 博客

泛型的下一步

Ian Lance Taylor and Robert Griesemer
16 June 2020

引言

距离我们上一次撰写关于在 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 中的版本将是 Go 1.17,计划于 2021 年 8 月发布。当然,实际情况中可能会有不可预见的问题,因此这只是一个乐观的时间表;我们无法做出任何确定的预测。

反馈

关于语言变更反馈的最佳方式是通过邮件列表 golang-nuts@googlegroups.com。邮件列表并非完美,但对于初步讨论来说,它们似乎是我们的最佳选择。在撰写关于设计草案的邮件时,请在主题行的开头加上 [generics],并针对不同的具体议题开启不同的讨论串。

如果您在泛型类型检查器或转换工具中发现了错误,请在标准的 Go 问题跟踪器 go.dev/issue 中提交。请在问题标题的开头加上 cmd/go2go:。请注意,问题跟踪器并非讨论语言变更的最佳场所,因为它不提供讨论串功能,也不适合进行冗长的对话。

我们期待您的反馈。

致谢

我们尚未完成,但已经走了很长一段路。没有大量的帮助,我们不可能走到今天。

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

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

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

下一篇文章:保持您的模块兼容
上一篇文章:Pkg.go.dev 已开源!
博客目录