在Go 1.11之前,Go 使用 GOPATH 环境变量来管理代码包和依赖项。这种方式存在一些问题,例如:
- 全局 GOPATH 环境变量使得在不同的项目中使用不同版本的依赖项非常困难。
- 依赖项的版本管理需要手动管理,很难自动化处理。
- 依赖项的下载和更新需要手动执行命令,不够方便。 为了解决这些问题,Go 1.11引入了Go模块(Go Modules)系统。Go模块是一种新的依赖项管理方式,它使用 go.mod 文件来记录和管理代码包的依赖项,并且支持版本控制。
go.mod
go.mod 文件是由以下几个元素组成:
- module:指定模块的名称和路径。模块路径应该是唯一的,它是在版本控制中使用的标识符。例如,example.com/mymodule 是一个有效的模块路径。
- go:指定使用的Go版本。这个例子中使用的是 Go 1.16 版本。
- require:列出了当前模块所依赖的其他模块及其版本。这个例子中,依赖了 github.com/some/dependency和github.com/another/dependency 两个模块,分别使用 v1.0.0 和 v1.2.3 版本。
- replace:指定了替换规则,用于将一个模块替换为另一个模块或本地目录。这个例子中,将github.com/another/dependency 模块的 v1.2.3 版本替换为本地目录 ../local/dependency。
在require 或 replace 定义中依赖模块需要指定版本号,这里展开 go module 版本号的是怎么定义?
使用 go mod 之后,依赖包都是通过版本打 tag 的形式确定版本号。比如 github.com/mnhkahn/gogogo v1.0.9。每次都改动都是在累加低位的版本号。Go 在用的版本号协议semver (Semantic Versioning)。它定义的版本号格式是:
- v 所有版本号都是 v 开头。
- MAJOR 主版本号,例如有大的版本更新,导致 API 和之前版本不兼容。
- MINOR 次版本号,例如当你做了向下兼容的新 feature。
- PATCH 修订版本号,例如当你做了向下兼容的修复 bug fix。
go.sum
在 go module 中还有一个另外一个重要的文件就是 go.sum,该文件有什么作用? go.sum 文件是 Go module 系统生成的一个文本文件,用于记录当前模块所有依赖项的版本和 checksums。它的作用是确保依赖项的完整性和安全性,防止依赖项被篡改或替换。当使用 go get 或 go mod download 命令下载依赖项时,Go 会自动检查go.sum 文件中的 checksums,以确保依赖项没有被篡改或替换。如果 go.sum 文件中的 checksums 与下载的依赖项不匹配,Go 会发出警告或错误,防止使用被篡改的依赖项。因此,go.sum 文件是保证 Go 模块系统安全和可靠性的关键组成部分。
常用命令
- go mod init:初始化一个新的模块,创建一个go.mod文件。
- go mod tidy:检查项目中使用的依赖项,并移除无用的依赖项。
- go mod vendor:将所有依赖项复制到项目的vendor目录中。
- go mod download:下载所有需要的依赖项。
- go mod graph:打印模块依赖关系的图形表示。
- go mod verify:验证依赖项的checksums,以确保它们没有被篡改。
- go mod edit:编辑go.mod文件。
- go mod why:说明为什么需要使用特定的依赖项。
- go mod tidy -v:显示go mod tidy的详细输出,包括哪些依赖项被移除。
- go list -m all:列出所有模块及其依赖项。
常见问题
go module 为什么使用 replace 而不直接修改 require 中依赖的版本?
使用 replace 的主要原因是为了方便在开发过程中进行本地调试。在某些情况下,我们可能需要修改某个依赖包的源代码,然后在项目中运行修改后的代码,以便进行调试和测试。如果直接修改 require 中依赖的版本,那么每次更新依赖包时都需要手动修改,非常繁琐。而使用 replace 可以将依赖包替换成本地的代码,这样就可以方便地进行本地调试。另外,使用 replace 还可以方便地使用自己修改过的第三方库。有些时候,我们可能需要修改某个第三方库的源代码以适应特定的需求,但是这个库的维护者可能不会接受我们提交的修改。这时,我们可以使用 replace 将依赖包替换成自己修改过的版本,这样就可以方便地使用自己的代码,而不必依赖第三方库的维护者。
备注:
感谢兴趣的同学欢迎关注公众号,定时更新相关技术文档。