最小版本抉择(MVS)

未匹配的标注

Go 在构建包时使用一种称为最小版本选择 (MVS) 的算法来选择一组模块版本。 Russ Cox在Minimal Version Selection中详细描述了 MVS  。

从概念上讲,MVS 在模块的有向图上运行,由 go.mod 文件 指定。 图中的每个顶点代表一个模块版本。 每条边代表依赖项的最低要求版本,使用 require 指令指定。 在主模块的 go.mod 文件中,使用replaceexclude 指令修改图形。

MVS 生成 构建列表 作为输出,即用于构建的模块版本列表。

MVS 从主模块开始(图中没有版本的特殊顶点),并遍历图,跟踪每个模块所需的最高版本。在遍历结束时,所需的最高版本构成构建列表:它们是满足所有要求的最低版本。

可以使用命令 go list -m all 检查构建列表。 与其他依赖管理系统不同,构建列表不保存在“锁定”文件中。 MVS 是确定性的,当发布新版本的依赖项时,构建列表不会改变,因此 MVS 用于在每个模块感知命令的开头计算它。

考虑下图中的示例。主模块需要模块 A 和 模块 B 最低 1.2 版本,A 1.2 和 B 1.2 分别依赖 C 1.3 和 C 1.4, C 1.3 和 C 1.4 都依赖 D 1.2。

图片

MVS 访问并加载所有标蓝版本模块的 go.mod 文件。在图上遍历结束时,MVS 返回一个包含粗体版本的构建列表:A 1.2、B 1.2、C 1.4 和 D 1.2。请注意,可以使用更高版本的 B 和 D,但 MVS 不会选择它们,因为不需要它们。

替换

在主模块的go.mod文件中,可以使用 replace 指令 来替换模块内容(包括其 go.mod 文件)。 replace 指令可能适用于模块的指定版本或所有版本。

因为替换的模块可能依赖不同的版本,替换会更改模块图。

考虑下面的示例,其中 C 1.4 已被 R 替换。R 取决于 D 1.3 而不是 D 1.2,因此 MVS 返回包含 A 1.2、B 1.2、C 1.4(替换为 R)和 D 1.3 的构建列表。

替换的模块版本图

Exclusion

在主模块的 go.mod 文件中,也可以使用 exclude 指令 在特定版本中排除一个模块。

排除也会改变模块图。当一个版本被排除时,它被从模块图中移除,对它的要求被重定向到下一个更高版本。

请看下面的例子。C 1.3 已经被排除。MVS 会像 A 1.2 要求 C 1.4(下一个更高版本)而不是 C 1.3 一样行事。

图片

升级

go get 命令可以用来升级一组模块。为了执行升级,go命令在运行 MVS 之前改变了模块图,增加了从访问的版本到升级后的版本。

看下面的例子。模块 B 可以从 1.2 升级到 1.3,C 可以从 1.3 升级到 1.4 ,D 可以从 1.2 升级到 1.3。

Module version graph with upgrades

升级(和降级)可以增加或删除间接的依赖关系。在这种情况下,E 1.1 和 F 1.1 在升级后出现在构建列表中,因为 E 1.1 是 B 1.3 所需要的。

为了保持升级,go命令更新go.mod中的需求。它将改变 B 的需求为 1.3 版本。它还将增加对 C 1.4和 D 1.3 的需求,并加上//间接注释,因为这些版本不会被选中。

降级

go get命令也可以用来降低一组模块的等级。为了执行降级,go命令通过移除降级后的版本来改变模块图。它也会移除依赖于被移除版本的其他模块的版本,因为它们可能与降级后的依赖版本不兼容。如果主模块需要一个被降级移除的模块版本,该需求将被改变为未被移除的先前版本。如果没有以前的版本,需求将被放弃。

考虑下面的例子。 假设发现 C 1.4 存在问题,因此我们降级到 C 1.3,把C 1.4 从模块图中删除。 因为 B 需要 C 1.4 或更高版本,B 1.2 也被删除, 主模块对B的要求改为1.1。

降级的模块版本图

go get 也可以完全删除依赖项,在参数后使用 @none 后缀。 这种类似于降级。 命名模块的所有版本都从模块图中删除。

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

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/go-mod/1.17/min...

译文地址:https://learnku.com/docs/go-mod/1.17/min...

上一篇 下一篇
贡献者:4
讨论数量: 0
发起讨论 只看当前版本


暂无话题~