gomod 的作用
正常情况下,当我们在 go 文件里 import 依赖包之后,在第一次构建程序时,就会拉取依赖包的最新版本到本地环境上。
如果我们使用 docker 或 k8s 这种每次都会重新构建环境的发布方式时, 那么每次都会 go get 到最新的依赖包。
而这种部署方式是有问题的,因为谁也不知道最新的依赖包修改了哪些内容。如果每次能够拉取指定的版本,那么就可以解决这个问题了,这就是 go mod 所解决的问题。
在 go 1.11 之前也有类似的版本解决方案,比如 像 dep 或者 vendor。后来 golang 官方在 1.11 推出了对应的版本管理工具: go module,也就是我们经常在项目里看到的 go mod 文件。
在这个文件里记录了当前项目里所有的依赖包名以及对应的版本号,后续在构建编译时,就会根据对应的版本号去拉取依赖包。
gomod 文件的创建
命令: go mod init 项目名
比如,我的项目是 manage, 那么就可以这样使用:
go mod init manage
此时就会在当前项目下生成 gomod 文件:
注意, 如果当前的项目是要给外部使用的,最好是配合代码仓库命名,比如
go mod init github.com/lincoln/manage
以便其他项目可以go get 引用得到。
依赖包的版本生成
上面的命令只是生成一个 gomod 文件,至于依赖包的版本号信息暂时是还没有生成的,可以使用下面2个命令进行获取:
命令1:go get 包名
如果依赖包比较多,那么go get 就比较麻烦了。可以使用另外一个命令:
命令2:go mod tidy
这个命令将会扫描所有我们 import 到的包,并生成对应的记录到 gomod 文件里。
这里的 v2.1.0 是因为引用的 go-cache 包在 github 上已经打标签了,所以有 v2.1.0 类似的字样出现,后面有 incompatible 是因为 go-cache 包的命名没有遵循官方规范,所以加了 incompatible 加以区分。
如果引用的包没有打过标签,那就有其他的版本记录生成规则, 比如
v0.0.0-20210501091049-10806f459f65
就表示版本号 + 日期 + 主分支最新的 commit 哈希值前缀。
此外,我们还发现除了 gomod 文件之外,还有 gosum 文件。此文件主要是用来记录依赖包的 hash 值,防止部署到新环境时,重新拉取的包与之前本地拉取的包不一致。
gomod 文件的使用技巧
1.引用分支最新的包
默认情况下,go mod tidy 将会拉取主分支的最新代码作为版本记录。
如果我们有多个项目在同时开发,假设都是在 develop 分支上时。
为了能拉取到对应的分支代码,我们可以手动修改 gomod 引用包的版本名字,替换为对应的分支名,比如改为:
require github.com/patrickmn/go-cache develop
然后使用 go mod tidy 命令,此时就会自动的获取 develop 分支的最新代码了。(注:此处只是演示,并不真实存在 go-cache 的 develop 分支)
2.引用本地开发的代码
golang 是根据 gomod 文件来构建程序的,如果我们引用了其他项目代码,那每次就得先提交到代码仓库,然后重新构建 gomod 文件才能引用到新的代码。
为了能直接引用本地正在开发的包,又不频繁提交代码,我们可以使用下面这个命令
replace github.com/patrickmn/go-cache => 本地项目包的地址
这样就可以在构建项目时,使用本地开发的包了, 等到所有项目都开发完毕,再最后重新构建 gomod 文件。
3.查看依赖包的历史版本
使用 go mod tidy 命令时总会拉取最新版本的依赖包,但当我们只想 import 某个历史版本时,就可以使用下面的命令来获取历史版本号了:
go list -m -versions github.com/patrickmn/go-cache
执行结果:
github.com/patrickmn/go-cache v1.0.0 v2.0.0+incompatible v2.1.0+incompatible
然后当我们想引用 v1.0.0 时,就可以这样改写了:
require github.com/patrickmn/go-cache v1.0.0
go module 其他命令
go list -m all :列出当前项目包名以及所有依赖到的包
go mod vendor: 将引用的包都生成到当前项目的 vendor 包下,这样可以不用每次重新构建时去拉取对应的包,直接加入到自己的 git 代码仓库管理中, 直接 git pull 即可。
另外,有点要注意的就是,如果我们在gomod 文件里手动添加了某个依赖包,但实际在项目里并没有使用到这个依赖包时,那么在执行 go mod tidy 构建时,就会自动删除这个依赖包的相关记录。