Golang: Command: Mod

 15th September 2022 at 6:34pm

Go 在 1.11 提出了 Go Module 作为 Go 的包管理模式。

官方文档在 这里,提供了非常多的常用流程。完整的参考文档在 这里

Go 并不强制使用 go module。当在本地磁盘查找一个库时,go 有两种做法:

  • 传统方式:从 GOPATH 或者项目的 vendor 目录中寻找
  • go module 方式:根据 go.mod, go.sum 来安装或者寻找包。包默认放在 $GOPATH/pkg/mod

新版本的 Go 中,go module 方式成为默认方式。

加速包拉取

可以设置 GOPROXY 环境变量为 七牛运营的中国镜像,下载速度极快:

go env -w GOPROXY="https://goproxy.cn,direct"

初始化新仓库

使用 go mod init <your-module-name>,比如 go mod init github.com/onlyice/my-go-module

添加新依赖库

在工程目录中,使用 go get <your-package>[@version]。比如 go get gorm.io/gorm。加入 -u 参数,会把你要加的库及其依赖,升级到最新的 minor.patch 版本。-u=patch 的话,只升级 patch 版本,不升级 minor 版本。再加入 -t 参数,会对库的 test 依赖也进行升级。

加入新依赖库后,不要急着 go mod tidy 去生成它的 go.sum 条目。先要在代码中 import 此包;否则 go mod tidy 会认为你没有用到这个包,把它从 go.mod 文件中去除。

如何查看包的依赖路径?

go mod why [packages] 可以用来解释一个包是如何被依赖到的,但对于每个包,它只会显示一个最短路径的依赖。

go mod graph 可以把包之间的直接和间接依赖都打出来。可以在其中检索你想看的包。

多模块仓库

多模块仓库指,一个仓库中有多个模块。例如,对于下面这个仓库的目录结构:

myrepo
└── metaservice
    ├── go.mod
    ├── go.sum
    ├── option.go
    └── store.go
└── userservice
    ├── go.mod
    ├── go.sum
    ├── option.go
    └── store.go

好处是,假如 metaservice 依赖了 foo 包,userservice 依赖了 bar 包。对于只需要依赖 metaservice 的用户来说,它只会引入 foo 作为间接依赖,而不会引入 bar 包。

这种仓库下,发版本时打的 tag 需要是这样的:metaservice/v1.0.0userservice/v1.0.0。它们的用户 go get 时则按正常来即可:

go get github.com/user/repo/metaservice@v1.0.0

GitHub wiki 中有一份 Multi-Module Repositories 的 FAQ。

Go modules 如何维护一个包的多个版本?

Go modules 在 $GOPATH/pkg/mod 下存放它下载的依赖、VCS 缓存等。这里面的目录结构使其可以保存一个包的多个版本。

参考