关于 Go 包版本化的提议

本文为官方 Go Blog 的中文翻译,详见 翻译说明

Russ Cox
2018年3月26日

介绍

8年前,Go团队引入了goinstall(这导致了go get)以及Go开发人员如今所熟悉的去中心化的,类似于URL的导入路径。在发布goinstall之后,人们问的第一个问题是如何合并版本信息。我们承认我们不知道。长期以来,我们相信使用附加工具可以最好的解决软件包版本控制问题,并且我们鼓励人们创建一个。Go社区使用不同的方法创建了许多工具。每一个都帮我们更了解这个问题,但到了2016年中期,很明显现在有太多的解决方案。我们需要采用一个单一的官方的工具。

在2016年7月在GopherCon上开始社区讨论并持续到秋天之后,我们都相信答案是遵循Rust的Cargo所示例的软件包版本控制方法,其中包括标记的语义版本,清单,一个锁定文件,和一个[SAT解决器]](research.swtch.com/version-sat),... Boyer领导了一个团队来创建Dep,该团队遵循了这个粗略的计划,我们打算将其用作go命令集成的模型。但是随着我们对Cargo/Dep方法的更多了解,对我来说很明显Go将从一些细节的更改中受益,特别是在向后兼容方面。

兼容性的影响

Go 1的最重要的新功能不是语言上的功能。而是Go 1的对向后兼容性的强调。在此之前,我们大约每月发布一次稳定的发行快照,每个快照都有重大的不兼容更改。我们在Go 1发行后立即看到了对Go的兴趣和采用率的提高。我们相信对向后兼容性的保证使开发人员对使用Go做生产用途感到更加舒适,并且是Go如今受欢迎的重要原因。自2013年以来,Go 常问问题一直鼓励软件包开发人员提供相似的兼容性保证。我们将其称为导入兼容性规则:“如果旧程序包和新程序包具有相同的导入路径,则新程序包必须与旧程序包向后兼容。”

独立的,语义版本已经在很多语言的社区称为了事实上的标准,包括Go社区。使用语义版本控制,更高版本将预期与早先版本向后兼容,但只在单个主要版本内:v1.2.3必须与v1.2.1和v1.1.5兼容,但是v2.3.4不必与这些中任何一个兼容。

如果我们像大多数Go开发人员所期望的那样对Go软件包实施语义版本控制,那么导入兼容性规则要求不同的主要版本必须使用不同的导入路径。这种。这种观察是我们使用语义导入版本控制,其中从v2.0.0开始的版本在导入路径中要加入主要版本:my/thing/v2/sub/pkg

一年前,我坚信是否在导入路径中包含版本号在很大程度上是个人喜好问题,并且我对使用它们是否优雅表示怀疑。但是,最终的决定原来不是喜好而是逻辑上的问题:导入兼容性和语义版本控制需要语义导入版本控制。当我意识到这一点时,逻辑上的必要性使我感到震惊。

我还惊讶的返发现,还有第二种独立的逻辑途径可以进行语义导入版本控制:gradual code repair,或者部分代码升级。在大型程序中,期望程序中所有的程序包同时从特定依赖项的v1升级到v2版本是不现实的。相反,某些程序可以继续使用v1,而其他部分已经升级到v2这种情况必须成为可能。但是,程序已经构建了,并且程序最终的二进制包,必须同时包括v1和v2版本的依赖。给它们同样的导入路径会导致混乱,违反了我们所谓的导入唯一性规则:不同的包必须具有不同的导入路径。进行部分代码升级,导入唯一性,语义版本控制的唯一办法是同时采用语义导入版本控制。

当然可以构建使用语义版本控制的系统而不使用语义导入控制,但是只能通过放弃或者部分代码升级或者导入唯一性。Cargo允许部分代码升级通过放弃导入唯一性:在大型构建的不同部分一个给定的导入路径可以有不同的意义。Dep通过放弃部分代码升级来确保导入的唯一性:大型构建中涉及的所有包必须找到给定依赖的单个商定版本,从而增加了大型程序不可构建的可能性。Cargo坚持部分代码升级是正确的。这对于大规模软件的开发至关重要。Dep坚持导入唯一性也同样正确。对Go目前的verdoring支持的复杂运用可能违反导入唯一性。当他们出现时,所产生的问题对于开发人员和工具理解起来都是非常具有挑战性的。在部分代码升级和导入唯一性之间做出决定需要预测放弃哪个会造成更大伤害。语义导入版本使我们可以避免这个选择并且保留两者。

我也惊讶的发现兼容性有多大的简化了版本选择,这是对于一个给定构建决定使用哪些包版本的问题。Cargo和Dep的约束使得版本选择等同于解决布尔可满足性,这意味着确定甚至是否存在有效的版本配置将是一件昂贵的事情。然后可能会有许多有效的版本配置,没有明确的标准来选择“最佳”配置。依赖导入兼容性,Go可以使用简单的线性时间算法来找这个最佳配置,这样的配置始终存在。这个算法,我叫做最小版本选择,反过来消除了对单独的锁定文件和清单文件的需要。它用一个简短的配置文件替代他们,该文件由开发人员和工具直接编辑,仍然支持可复制的构建。

我们在Dep上的经验证明了兼容性的影响。在Cargo和早期系统的引导下,我们设计Dep放弃了导入兼容性作为采用语义版本控制一部分。我认为我们不是故意这样决定的;我们只是遵循了其他系统。使用Dep第一手的经验帮助了我们更好地理解了允许不兼容的导入路径会导致多少复杂性。通过引入语义导入版本控制来恢复导入兼容性规则,可以消除这种复杂性,从而使系统变得更加简单。

进度,一个原型和一个提案

Dep于2017年1月发布。它的基本模型-带有语义版本标记的代码,以及一个指定依赖要求的配置文件-是大多数Go verdoring工具迈出的明确一步,并且整合到Dep本身也是向前明确的一步。我全心全意的鼓励采用它,尤其是帮助开发者习惯于思考关于Go包版本的事情,既包括他们自己的代码也包括他们的依赖。当Dep显然在朝着正确的方向前进的同时,我一直对细节中的复杂性恶魔挥之不去。我特别担心Dep在大型程序中缺少对逐步代码升级的支持。在2017年的课程中,我与许多人交谈,包括Sam Boyer和其他包管理工作小组成员,但是我们没人能找到任何降低复杂性的明确方法。(我确实发现了许多增加它的方法。)到了年底,似乎SAT解决器和不够满意的构建是我们能做到的最好。

11月中旬,我再次尝试研究Dep如何支持渐进的代码升级,我意识到我们有关导入兼容性的旧建议意味着语义导入版本控制。这似乎是一个真正的突破。我写了一篇后来后来成为我的语义导入版本控制博客文章的初稿,并通过建议Dep采纳该协议作为总结。我将草案发送给了我一直在与之交谈的人们,它引起了强烈的反响:每个都喜欢或者讨厌它。我意识到在进一步传播该想法之前,我需要弄清楚语义导入版本控制的更多含义,因此我着手这样做。

在12月中旬,我发现导入兼容性和语义导入版本控制一起允许将版本选择缩小至最小版本选择。我写了一个基本的实现以确保我理解它,我花了一段时间学习为什么它这么简单的背后的理论,然后我写了一篇描述它的文章草稿。即便如此,我仍然不确定这种方法在像Dep这样的真正的工具中是否可行。很明显,需要一个原型。

一月份,我开始研究一个简单的go命令包装器,该包装器实现了语义导入版本控制和最小版本选择。琐碎的测试效果很好。临近月底,我的简单包装器就可以构建Dep,这是一个使用许多版本化软件包的真实程序。这个包装器仍然没有命令行接口-它正在构建Dep的事实使用几个字符串常量硬编码的-但是这种方法显然是可行的。

我在二月的前三周里将包装器变成了完整版本的go命令,vgo;写了一些介绍vgo的博客文章系列的草稿;并且与Sam Boyer,包管理工作组,和整个Go团队讨论。然后我花了2月的最后一周,与整个Go社区分享了vgo和其背后的想法。

除了导入兼容性,语义导入版本控制和最小版本选择的核心思想外,vgo原型还引入了一些较小但意义重大的更改,这些更改是由八年的goinstallgo get的经验推动的:Go模块的新概念,它是一个版本化为一个单元的软件包的集合;可验证且经过验证的版本;和go命令期间的版本感知,使在$GOPATH外工作和消除(大部分)verdor目录成为可能。

所有这些的结果就是我上周提交的官方Go建议。尽管它看起来像是一个完整的实现,但它仍然只是一个原型,我们都需要共同努力才能完成。你可以从golang.org/x/vgo 下载并尝试vgo原型,然后可以阅读版本化Go之旅以了解使用vgo是什么样子。

前方的道路

我上周提交的提案就是这样:一个初始提案。我知道Go团队有我看不到的问题,因为Go开发人员以许多我们不知道的聪明方式使用Go。提案反馈过程的目标是让我们大家共同努力,以找出并解决当前提案中的问题,以确保将来的Go版本中附带的最终实现对于尽可能多的开发人员而言效果良好。请指出有关提案讨论问题的问题。我将保持讨论摘要FAQ的更新。

为了使该建议成功,整个Go生态系统(尤其是当今的主要Go项目)将需要采用导入兼容性规则和语义导入版本控制。为了确保能够顺利进行,我们还将通过视频会议进行用户反馈,这些反馈涉及一些项目,这些项目对如何将新版本建议纳入其代码库中有疑问,或者对他们的经验有反馈。如果您有兴趣参加此类会议,请发送电子邮件至Stef Francia,电子邮件为spf@golang.org。

我们期待(最终!)为Go社区提供一个单一的正式答案,以解答如何将软件包版本控制纳入go get中。感谢所有帮助我们做到这一点的人,以及所有将帮助我们前进的人。我们希望在您的帮助下,我们可以交付Go开发人员会喜欢的东西。

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
上一篇 下一篇
Summer
贡献者:1
讨论数量: 0
发起讨论 只看当前版本


暂无话题~