gomod 的使用

643 阅读5分钟

前言

作为官方的包依赖管理工具 gomod,已经被广泛的使用于各个开源项目中了。自从有了它,腰不酸手不疼了,敲代码也更有劲了......o(∩_∩)o 所以,今天我们就来认识认识 gomod ,看看它是如何来解决我们的包管理问题!

gomod 产生背景

在我们开发程序时,经常会引用到第三方开源框架提供的方法。按 Go 以前的做法会先将开源项目的最新代码通过 go get 下载本地的 GOPATH 目录。然后在需要使用的时候,就到对应的 GOPATH 目录去查找了。

然而,这里需要考虑一个问题,就是不同时间点 go get 下载下来的代码可能是不一样的,因为第三方开源框架总会进行代码升级,此时不能保证各个开发者的本地环境依赖包都是同一个版本。

而这就无形中增加了维护的成本,每次升级得手动删除,然后重新引用。

特别是在使用 docker 或 k8s 这种需要重新构建环境的发布方式时, 更得注意这个问题了,因为谁也不知道最新的依赖包修改了哪些内容,是否有破坏性变更存在。

此时,就该 go mod 登场了,它通过在 go.mod 这个文件里记录了当前项目里所有依赖包的 git 仓库地址以及对应的版本号,来解决了包依赖管理的问题,后续在构建编译时,就会根据对应的版本号去拉取依赖包。也就是说只要我们维护了 gomod 文件,依赖问题就不再是问题了!!!

gomod 文件的创建

命令: go mod init 项目名

比如,我的项目是 manage, 那么就可以这样使用:

go mod init manage

此时就会在当前项目下生成 gomod 文件:

gomod 生成 注意, 如果当前的项目是要给外部使用的,最好是配合 git 仓库命名,比如

go mod init github.com/lincoln/manage

以便其他项目可以 go get 引用得到。

依赖包的版本生成

上面的命令只是生成一个 gomod 文件,至于依赖包的版本号信息暂时是还没有生成的,可以使用下面 2 个命令进行获取:

命令1go get 包名

如果依赖包比较多,那么 go get 就比较麻烦了。可以使用另外一个命令:

命令2go mod tidy

这个命令将会扫描所有我们 import 到的包,并生成对应的记录到 gomod 文件里。

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 会拉取主分支的最新代码作为版本记录。

如果我们有多个功能在同时开发,按常规操作,是需要新建各自的 feature 分支来开发的,而不会在主分支上直接开发的。

所以,当有其他模块需要引用分支代码时,我们就不能按常规操作 go mod tidy 了。

此时我们需要手动修改 gomod 引用包的版本名字,替换为对应的分支名,比如 gomod 文件改为:

require github.com/patrickmn/go-cache develop

然后再使用 go mod tidy 命令,Go 就会自动的去获取 develop 分支的最新代码了。(注:此处只是演示,并不真实存在 go-cache 的 develop 分支)

2)引用本地开发的代码

golang 是根据 gomod 文件来构建程序的,如果我们引用了其他项目代码,那每次就得先提交代码到 git 仓库,然后重新构建 gomod 文件才能引用到最新的代码。

为了能直接引用本地正在开发的包,又不频繁提交代码,我们可以使用下面这个命令

replace github.com/patrickmn/go-cache => 本地项目包的地址

这样就可以在构建项目时,本地联调了。等联调完毕,再一次性的提交代码到 git 仓库里。

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 list某个包,必须得先在此项目中引用了对应的包。例如,当前项目如果没有引用 go-cache 包,则go list是获取不到信息的。

go module 其他命令

go list -m all :列出当前项目包名以及所有依赖到的包

go mod vendor: 将引用的包都生成到当前项目的 vendor 包下,这样可以不用每次重新构建时去拉取对应的包,直接加入到自己的 git 代码仓库管理中, 直接 git pull 即可。

另外,有点要注意的就是,如果我们在 gomod 文件里手动添加了某个依赖包,但实际在项目里并没有使用到这个依赖包时,那么在执行 go mod tidy 构建时,就会自动删除这个依赖包的相关记录。

总结

go mod 的使用很简单,go mod initgo mod tidy,基本就能解决很多依赖问题了。这也是 Go 官方一直提倡的简洁、优雅。


感兴趣的朋友可以搜一搜公众号「 阅新技术 」,关注更多的推送文章。
可以的话,就顺便点个赞、留个言、分享下,感谢各位支持!
阅新技术,阅读更多的新知识。
阅新技术