gomod 使用

前言

作为官方的包依赖管理工具 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 个命令进行获取:

命令1:go get 包名

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

命令2:go 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 官方一直提倡的简洁、优雅。

上一篇:育儿资讯应用Winnie获400万美元,给国内同行带来什么启示?


下一篇:阿里云IoT芯片模组合作之美