Go 如何基于 MVS 解决依赖关系问题
2024-6-20 10:49:10 Author: cloudsjhan.github.io(查看原文) 阅读量:13 收藏

发表于 | 分类于 | 阅读次数: |

| 字数统计: 1,362 | 阅读时长 ≈ 5

摘要:文章主要介绍了 Go 如何解决依赖关系和版本冲突问题,以及模块管理系统,包括 go.mod 文件的作用、go get 和 go install 命令的使用

Go 使用一种名为 “最小版本选择(Minimal version selection)”(MVS)的方法来处理依赖关系和解决版本冲突。
MVS 听起来很复杂,但要点如下:它为每个模块挑选最低版本,以满足其他模块的所有要求。这样,它就能在满足所有相关需求的同时,尽可能减少依赖性。

例如,假设我们有三个模块:A、B 和 C。

模块 [email protected] 和模块 [email protected] 都依赖于模块 C。

但 A 需要 [email protected],B 需要 [email protected]

同时 C 也有一个更新的版本,即 2.4.1。

Go 如何决定使用哪个版本的 C?

如果选择的 2.3.2 版本与模块 B 不兼容怎么办?

Go 模块使用语义版本控制(semver)来处理兼容性问题。
如果模块遵循 semver,则任何破坏性修改都应修改主版本(major.minor.patch)。由于 2.3.0 和 2.3.2 两个版本的主要版本(2.3.x)相同,因此它们应该相互向后兼容。
模块作者有责任确保不同版本保持兼容。

如果 A 需要 3.0.0 版本的 C,这会破坏与 B 的兼容性,怎么办?

当模块达到主版本 2 或更高版本时,其路径会包含主版本号(如 /v2 或 /v3):

1
2
github.com/user/project/v2
github.com/user/project/v3

不同主要版本的模块被视为不同的模块。因此,我们可以在同一项目中同时使用 [email protected][email protected]

例如,我们的 go.mod 文件可能如下所示:

1
2
3
4
5
6
7
8
9
10
module yourproject

require (
github.com/user/A v1.0.0
github.com/user/B v1.0.0
)
require (
github.com/user/C/v2 v2.3.2 // indirect
github.com/user/C/v3 v3.0.0 // indirect
)

// indirect 注释表示这里的项目没有直接导入 C 模块,而是因为 A 或 B 需要它才导入的。

还有一个要注意点:go get 不会更新或添加缺失的测试依赖项。要包含这些依赖项,请使用 -t 标志,如 go get -t ./...

go get

这里举几个例子,看看 go get 在不同情况下是如何工作的。

使用 go get .或 go get ./…查找当前目录或其子目录中所有缺失的依赖项,并将其添加到 go.mod 文件中。
这意味着它会检查任何尚未列出的依赖项,并将其添加进来。除非你特别要求,否则它不会将现有的依赖项更新到最新版本,比如下一个例子中的 -u 标志。

1
go get -u .

在 go get .中使用 -u 标志,会将当前目录中的现有依赖项更新到最新的次版本或补丁版本。请记住,它不会更新到新的主版本,因为它们被视为不同的模块。
要将主模块的所有依赖项更新到最新版本,可以使用 go get -u ./...

在下面的几个情况下,即使不指定 -u 标志,go get 仍会更新过时或丢失的依赖项。

go get github.com/user/project

此命令下载模块 github.com/user/project,并将其添加到 go.mod 文件中。如果该模块已列在该文件中,则会将其更新为最新的次版本或补丁版本。基本上,如果你不指定版本(或版本查询后缀),它会假定你想升级到最新版本,就像使用 go get github.com/user/project@upgrade 一样。

go get github.com/user/[email protected]

此命令将模块更新到指定版本,即 v1.2.3。根据当前的版本,它可能会升级或降级模块以匹配该版本。

go install: build and install packages

与下载依赖项以便在项目中使用其源代码不同,go install 会将依赖项的源代码编译成二进制文件,并将其移动到 $GOPATH/bin 目录中进行安装。这样就可以在终端上使用它了。

例如:

1
$ go install golang.org/x/tools/gopls@latest

运行该命令并查看 $GOBIN 文件夹(我们之前提到过)后,你会在其中看到一个名为 gopls 的可执行文件。如果 $GOBIN 在您的 $PATH 中,您就可以在终端中运行 gopls。

如果只是在没有任何参数的情况下运行 go install 会怎样呢?
go install 就会下载缺失的依赖项,并在当前目录下构建当前模块。
这导致一些人误用 go install 来管理依赖关系,因为它确实会下载依赖关系。但这并不是它的主要工作,它实际上是要构建你的项目,并将生成的二进制文件安装到 $GOBIN 目录中。

go install 用于构建和安装软件包,而 go get 用于管理依赖关系。有些开发者经常会感到困惑,这是因为在旧版本的 Go 中,go get 确实是用来在更新 go.mod 文件后构建软件包,然后将它们安装到 $GOPATH/bin。

但从 Go 1.16 开始,go install 成为了构建和安装的首选命令,而 go get 则专注于管理 go.mod 文件中的需求。


-------------The End-------------

cloud sjhan wechat

subscribe to my blog by scanning my public wechat account

0%


文章来源: https://cloudsjhan.github.io/2024/06/20/Go-%E5%A6%82%E4%BD%95%E5%9F%BA%E4%BA%8E-MVS-%E8%A7%A3%E5%86%B3%E4%BE%9D%E8%B5%96%E5%85%B3%E7%B3%BB%E9%97%AE%E9%A2%98/
如有侵权请联系:admin#unsafe.sh