介绍
自从我们上次写下关于在Go中加入泛型的可能性的文章以来,已经快一年了。现在是该更新的时候了。
设计的更新
我们一直在继续完善泛型设计草案。我们已经为它写了一个类型检查器:一个可以解析设计草案中描述的使用泛型的Go代码并报告任何类型错误的程序。我们已经写了示例代码。我们还收集了许多人的反馈–感谢他们提供的反馈!
根据我们所了解到的情况,我们发布了一个更新的设计稿。最大的变化是我们放弃了contracts的概念。contracts和interface之间的区别让人很困惑,所以我们要消除这种区别。类型参数现在受到接口类型的约束。接口类型现在允许包含类型列表,不过只有在用作约束时才允许;在之前的设计草案中,类型列表是contracts的一个特征。更复杂的情况下会使用参数化的接口类型。
我们希望大家会发现这个设计稿更简单,更容易理解。
实验工具
为了帮助决定如何进一步完善设计草案,我们正在发布一个翻译工具。这是一个允许人们对使用设计草案中描述的泛型版本编写的代码进行类型检查和运行的工具。它的工作原理是将泛型代码翻译成普通的Go代码。这个翻译过程会带来一些限制,但我们希望它能让人们感受到泛型Go代码的样子。如果泛型代码被语言接受,那么它们的真正实现将以不同的方式进行。(我们才刚刚开始勾勒出直接编译器实现的样子。)
这个工具可以在Go playground的一个变体上获得,网址是https://go2goplay.golang.org。 这个playground的工作原理和通常的Go playground一样,但它支持通用代码。
你也可以自己构建和使用这个工具。它在主Go repo的一个分支中。按照关于Go from source的说明。在这些 release tags的地方,改成运行git checkout dev.go2go。然后按照指示构建Go工具链。
翻译工具的文档在 README.go2go 中有说明。
接下来的步骤
我们希望这个工具能给Go提供一个尝试泛型的机会。我们希望学习的主要有两点。
首先,泛型代码是否有意义?它的感觉像Go吗?人们会遇到什么惊喜?错误信息是否有用?
第二,我们知道很多人都说Go需要泛型,但我们不一定知道这到底是什么意思。这个设计草案是否以有用的方式解决了这个问题?如果有一个问题让你觉得 “如果Go有了泛型,我就能解决这个问题”,那么在使用这个工具时,你能解决这个问题吗?
我们将利用从Go社区收集到的反馈来决定如何推进。如果设计草案广受好评,不需要做重大修改,下一步将是正式的语言修改提案。为了设定期望值,如果大家对设计草案完全满意,并且不需要进一步调整,那么最早可以在Go中加入泛型的时间是Go1.17版本,计划于2021年8月发布。当然,在现实中,可能会有不可预见的问题,所以这是一个乐观的时间表,我们无法做出任何明确的预测。
反馈意见
为语言修改提供反馈的最佳方式是给邮件列表golang-nuts@googlegroups.com发邮件。邮件列表是不完美的,但它们似乎是我们进行初步讨论的最佳选择。当写设计稿时,请在主题行的开头加上[generics],并为不同的特定主题启动不同的线程。
如果您在generics类型检查器或翻译工具中发现了bug,应该将其归档到标准的Go问题追踪器中,网址为https://golang.org/issue 。请以 cmd/go2go:作为问题标题的开头。请注意,问题跟踪器并不是讨论语言修改的最佳场所,因为它不提供线程,也不太适合进行冗长的对话。
我们期待着您的反馈。
鸣谢
我们还没有完成,但我们已经走了很长的路。如果没有很多人的帮助,我们就不会有今天。
我们要感谢Philip Wadler和他的合作者,感谢他们正式思考了Go中的generics,并帮助我们澄清了设计的理论方面。他们的论文Featherweight Go分析了Go的限制版本中的generics,他们已经在GitHub上开发了一个原型。
我们还要感谢那些对早期版本的设计稿提供详细反馈的人。
最后但绝对不是最不重要的,我们要感谢Go团队中的许多人,Go问题跟踪器的许多贡献者,以及其他所有对早期设计稿分享想法和反馈的人。我们阅读了所有的内容,我们很感激。没有你们,我们就不会有今天。