如何对Go中的工具进行版本管理?
版本依赖是关键,因为它允许我们确切地知道最终的工件会是什么样子,它让我们创建确定的构建,只要依赖不改变,工作就一样。关于工具的依赖性,特别是那些用Go编写的工具,版本控制过程类似于我们在使用Go模块时的典型做法。
如何对Go中的工具进行版本管理?
虽然没有必要,但我建议你安装 direnv,这个工具允许你按目录进行沙盒环境变量,因为它允许我们这样做,所以我们可以为一个具体的目录定义我们自己的PATH 和GOBIN ,这在实践中意味着,通过这样做,我们可以安装与我们当前工作的项目相对应的二进制文件,而不使它们在我们的系统中全球可用。
这个 作为依赖关系的工具范式是我们需要的,基本上定义一个文件,空白地导入我们需要的所有工具,并使其只适用于一个具体的标签。
这种模式肯定是可行的,但我喜欢更进一步,与其让tools.go 文件成为主Go模块的一部分,不如在internal 包中定义另一个独立的Go模块,例如internal/tools ;这样做的目的是为了让这些依赖关系与主Go模块明确隔离。
例如,假设我们依赖 sqlc,我们将在internal/tools 中创建一个新的模块,然后我们将创建一个名为:internal/tools/tools.go 的文件,内容如下。
package tools
import (
_ "github.com/kyleconroy/sqlc/cmd/sqlc"
)
接下来,我们将go get 。
go get github.com/kyleconroy/sqlc/cmd/sqlc@latest
这是为了使go.sum 被正确地填充,通过这一切,如果我们的Go模块的用户决定导入主包,他们将不需要我们使用的工具所需要的包,而只需要主包所需要的包;而且因为我们把我们的tools 包放在internal ,所以外部用户也不可能导入这个包。
关于最终的internal/tools 包的更多细节,请参考源代码。
总结
版本管理是最基本的,因为我们可以确定在构建我们的程序时需要的确切的依赖关系,这同样适用于我们的程序需要构建的外部程序,比如说linters或代码生成器;把所有的东西都标记为我们仓库的一部分,这样无论如何都可以以同样的方式构建工件,因为我们可以确定我们所依赖的版本。