Go依赖管理

190 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第3天,详细了解了go依赖管理的发展路程 包的依赖管理经历了三个阶段:GOPATH、Go Vendor、Go Module

GOPATH

gopath可以理解为工作目录,这个目录下有如下目录结构

bin:存放编译后生成的二进制可执行文件 pkg:存放编译后生成的 .a 文件 src:存放项目的源代码,可以是你自己写的代码,也可以是你 go get 下载的包 将你的包或者别人的包全部放在 $GOPATH/src 目录下进行管理的方式,我们称之为 GOPATH 模式。

在GOPATH中,没有版本的概念

你无法在你的项目中,使用指定版本的包,因为不同版本的包的导入方法也都一样 其他人运行你的开发的程序时,无法保证他下载的包版本是你所期望的版本,当对方使用了其他版本,有可能导致程序无法正常运行 在本地,一个包只能保留一个版本,意味着你在本地开发的所有项目,都得用同一个版本的包,这几乎是不可能的。

go vendor

解决了GOPATAH无法使用多版本库的问题,解决的办法是:在每个项目下都创建一个vendor目录,每个项目所需的依赖都只会下载到自己vendor目录下,项目之间依赖的包互不影响

搜索依赖包的优先级如下

  • 当前包下的vendor目录
  • 向上级目录查找,直到src下的vendor目录
  • 在GOROOT目录下查找
  • 在GOPATH下面查找依赖包

缺点:

  1. 无法对第三方包的集中式管理。当多个项目用到同一个包的同一个版本时,该包会存在于该机器上的不同目录下(即不同vendor下),浪费了磁盘空间
  2. 当想要开源项目时需要把项目+所有依赖的包一并传上去,而且别人也需要把依赖的包在拷贝项目代码时也一起下载,这样子才能保证项目正常运行

Go Module

启用go mod之后(把GO111MODULE设置成on),可以脱离GOPATH来创建项目。go mod会将所有的依赖包安装在$GOPATH/pkg目录下

go.mod

image-20230120160438092.png

  • 第一行:模块的引用路径,即引用项目中其他包时的根路径,如图:

    image-20230120160622435.png

  • 第二行:项目使用go的版本

  • 第三行:项目所需的直接依赖包及其版本

image-20230120184934533.png

在go.mod中会出现两个flag

exclude:忽略指定版本的依赖包

replace:由于在国内访问golang.org/x的各个包都需要f.g,因此可以在go.mod中使用replace替换成github上对应的库

go.sum

image-20230120162039803.png

每一行都是由模块路径,模块版本,哈希检验值组成,其中哈希检验值是保证当前缓存的模块不会被篡改。hash是以h1:开头的字符串,表示生成的checksum(校验和)的算法是第一版的hash算法(sha256)

有的包只有一行

 <module> <version>/go.mod <hash>

而有的包有两行

 <module> <version> <hash>
 <module> <version>/go.mod <hash>

有两行的包,区别就在于hash值不一样,一个是h1:hash,一个是go.mod h1:hash

h1:hash和go.mod h1:hash两者,要不同时存在,要不只存在go.mod h1:hash。不存在h1:hash的情况是Go认为肯定用不到某个模块版本的时候就会省略h1:hash

注意

go.mod和go.sum是go modules版本管理的指导性文件,因此go.mod和go.sum文件都应该提交到Git仓库中,避免其他人使用项目时,重新生成的go.mod和go.sum与你开发的基准版本不一致

go mod命令使用

  • go mod init:初始化go mod, 生成go.mod文件,后可接参数指定 module 名,上面已经演示过。
  • go mod download:手动触发下载依赖包到本地cache(默认为$GOPATH/pkg/mod目录)
  • go mod graph: 打印项目的模块依赖结构
  • go mod tidy :添加缺少的包,且删除无用的包
  • go mod verify :校验模块是否被篡改过
  • go mod why: 查看为什么需要依赖
  • go mod vendor :导出项目所有依赖到vendor下
  • go mod edit :编辑go.mod文件,接-fmt参数格式化 go.mod 文件,接-require=golang.org/x/text添加依赖,接-droprequire=golang.org/x/text 删除依赖,详情可参考 go help mod edit
  • go list -m -json all:以 json 的方式打印依赖详情