Go 博客

Go 2,我们来了!

Robert Griesemer
2018 年 11 月 29 日

背景

在 GopherCon 2017 大会上,Russ Cox 通过他的演讲Go 的未来 (博客文章) 正式启动了关于下一个 Go 大版本的思考过程。我们非正式地将这个未来的语言版本称为 Go 2,尽管我们现在明白它将通过增量步骤而非一次大爆炸式的单一主要发布版本到来。然而,Go 2 仍然是一个有用的称谓,至少为讨论那个未来的语言版本提供了一种方式,所以我们暂时继续使用它。

Go 1 和 Go 2 之间的一个主要区别在于谁将影响设计以及如何做出决策。Go 1 是一个小团队的努力成果,受外部影响不大;Go 2 将更多地由社区驱动。经过近 10 年的使用,我们对这门语言和库有了很多最初不知道的认识,这只有通过 Go 社区的反馈才得以实现。

2015 年,我们引入了提案流程来收集特定类型的反馈:关于语言和库变更的提案。由资深 Go 团队成员组成的委员会一直在定期审查、分类和决定收到的提案。这项工作进展顺利,但作为流程的一部分,我们忽略了所有不向后兼容的提案,而是简单地将它们标记为 Go 2。2017 年,我们还停止进行任何类型的增量向后兼容的语言更改,无论多小,转而支持一个更全面的计划,该计划考虑了 Go 2 的更广阔前景。

现在是时候对 Go 2 提案采取行动了,但在此之前,我们需要一个计划。

状态

撰写本文时,大约有 120 个标记为 Go 2 proposal 的未解决问题。每个问题都提出了重大的库或语言变更,这些变更通常不满足现有的Go 1 兼容性保证。Ian Lance Taylor 和我一直在处理这些提案,并对其进行了分类(Go2CleanupNeedsDecision 等),以了解情况并方便后续处理。我们还合并了相关的提案,并关闭了那些看起来明显超出 Go 范围或无法采取行动的提案。

剩余提案中的想法可能会影响 Go 2 的库和语言。早期出现了两个主要主题:支持更好的错误处理和泛型。今年 GopherCon 上已经发布了这两个领域的设计草案,还需要进行更多探索。

那剩下的呢?我们受到这样一个事实的约束:现在有数百万 Go 程序员和大量的 Go 代码,我们需要将它们全部带入 Go 2,以免导致生态系统分裂。这意味着我们不能进行很多更改,并且我们将要进行的更改需要仔细选择。为了取得进展,我们正在为这些重大的潜在更改实施新的提案评估流程。

提案评估流程

提案评估流程的目的是收集对少量选定提案的反馈,以便做出最终决定。该流程或多或少与发布周期并行运行,包含以下步骤

  1. 提案选择。Go 团队选择少量Go 2 提案,这些提案看起来值得考虑接受,但尚未做出最终决定。有关选择标准的更多信息,请参见下文。

  2. 提案反馈。Go 团队发布公告,列出选定的提案。公告向社区解释了推进选定提案并收集每个提案反馈的初步意图。这让社区有机会提出建议和表达担忧。

  3. 实现。根据反馈,实施提案。这些重要的语言和库变更的目标是在即将到来的发布周期第一天准备好提交。

  4. 实现反馈。在开发周期中,Go 团队和社区有机会实验新功能并收集进一步的反馈。

  5. 发布决定。在三个月开发周期结束时( just在发布前开始为期三个月的仓库冻结时),Go 团队根据发布周期期间收集的经验和反馈,最终决定是否发布每个更改。这提供了一个机会来考虑更改是否带来了预期的好处或产生了任何意外的成本。一旦发布,更改将成为语言和库的一部分。被排除的提案可能会重新评估或永久拒绝。

通过两轮反馈,这个流程倾向于拒绝提案,这有望防止特性蔓延并有助于保持语言的小巧和简洁。

我们无法对每个未解决的 Go 2 提案都走一遍这个流程,数量实在太多了。这就是选择标准发挥作用的地方。

提案选择标准

一项提案至少必须

  1. 解决许多人的重要问题,

  2. 对其他所有人的影响最小,并且

  3. 有一个清晰且易于理解的解决方案.

要求 1 确保我们进行的任何更改都能尽可能多地帮助 Go 开发者(使他们的代码更健壮、更容易编写、更可能正确等等),而要求 2 则确保我们谨慎地尽量少地伤害开发者,无论是破坏他们的程序还是导致其他变动。根据经验法则,我们应该争取通过一项给定的更改帮助的开发者数量至少是我们伤害的开发者数量的十倍。不影响实际 Go 使用的更改,其好处相对于巨大的实现成本而言为零,应该避免。

没有要求 3,我们就无法实现该提案。例如,我们相信某种形式的泛型可能为很多人解决一个重要问题,但我们还没有一个清晰且易于理解的解决方案。这没关系,这只意味着在考虑该提案之前,需要重新评估。

提案

我们认为这是一个很好的计划,应该对我们很有帮助,但重要的是要明白这只是一个起点。随着流程的使用,我们会发现它运作不畅的地方,并根据需要对其进行改进。关键在于,除非我们在实践中使用它,否则我们不会知道如何改进它。

一个安全的起点是少量的向后兼容的语言提案。我们已经很长时间没有进行语言更改了,所以这让我们回到了那种模式。此外,这些更改不会要求我们担心破坏现有代码,因此它们可以作为完美的试验气球。

说了这么多,我们为 Go 1.13 版本提出了以下 Go 2 提案的选择(提案评估流程的步骤 1)

  1. #20706 基于 Unicode TR31 的通用 Unicode 标识符:这解决了使用非西方字母表的 Go 程序员的一个重要问题,并且对其他任何人几乎没有影响。有一些规范化问题需要我们回答,并且社区反馈将很重要,但之后实现路径是明确的。请注意,标识符导出规则不会受此影响。

  2. #19308, #28493 二进制整数文字和数字文字中对 _ 的支持:这些是相对较小的更改,但在许多程序员中似乎非常受欢迎。它们可能没有完全达到解决“重要问题”的门槛(十六进制数字目前为止运行良好),但它们在这方面使 Go 与大多数其他语言持平,并缓解了部分程序员的痛点。它们对不关心二进制整数文字或数字格式的其他人的影响最小,并且实现是明确的。

  3. #19113 允许带符号整数作为移位计数:据估计,所有非常量移位中约有 38% 需要(人工)uint 转换(详见该问题)。这项提案将清理大量代码,使移位表达式与索引表达式以及内置函数 cap 和 len 更好地同步。它将主要对代码产生积极影响。实现是明确的。

下一步

通过这篇博客文章,我们已经执行了提案评估流程的第一步,并开始了第二步。现在轮到你们,Go 社区,就上面列出的问题提供反馈了。

对于每个我们收到清晰且赞同反馈的提案,我们将继续进行实现(流程的步骤 3)。因为我们希望在下一个发布周期的第一天(暂定 2019 年 2 月 1 日)实现这些更改,所以这次我们可能会稍微提前开始实现,以便留出整整两个月的反馈时间(2018 年 12 月,2019 年 1 月)。

在 3 个月的开发周期(2019 年 2 月至 5 月)内,选定的功能将被实现并在 tip 上可用,所有人都有机会体验它们。这提供了另一个反馈机会(流程的步骤 4)。

最后,在仓库冻结(2019 年 5 月 1 日)后不久,Go 团队会做出最终决定,是永久保留新功能(并将其包含在 Go 1 兼容性保证中),还是放弃它们(流程的最后一步)。

(由于在仓库冻结时可能需要移除某个功能,因此实现方式需要使得该功能可以在不破坏系统其他部分稳定性的情况下禁用。对于语言更改,这可能意味着所有与功能相关的代码都由内部标志保护。)

这将是我们第一次遵循这个流程,因此仓库冻结也将是一个回顾流程并在必要时进行调整的好时机。让我们看看效果如何。

祝评估愉快!

下一篇文章:2019 年的 Go Modules
上一篇文章:Go 的九年
博客索引