Go语言之依赖管理:go mod的使用详解

1,023 阅读2分钟

我正在参加「掘金·启航计划」

1、前言

在 Go1.11 前使用 GOPATH模式,将你的包或者别人的包全部放在gopath/src目录下进行管理,这样就会碰到一个问题,无法做到不同项目依赖同一个库的不同版本,你无法在你的项目中使用指定版本的包,因为不同版本的包导入方法也都一样,当你运行别人开发的程序时,无法保证下载的包版本是你所期望的版本,当使用了其他版本,有可能导致程序无法正常运行。

为了解决不同项目下无法使用多个版本库的问题,go1.5开始支持vendor,在每个项目下都创建一个vendor目录,每个项目所需要的依赖都只会下载到自己vendor目录,项目之间的依赖包互不影响,虽然解决了一些问题,但存在一些弊端,如果多个项目用到同一个包的同一个版本,这个包会存在该机器上的不同目录,造成磁盘空间浪费,没法对第三方包进行集中式的管理,为了完美的解决包的版本依赖问题,v1.11版go modules 横空出世。

2、Go Module

Go Module是Go1.11开始引入,解决了之前依赖管理系统存在的诸如无法依赖同一个库的多个版本问题。1.12之前使用需要配置环境变量GO111MODULE=on,而1.13以后变量默认值为auto。

2.1、配置

GO111MODULE有三个值可以选:off、on、auto(默认值);

  1. GO111MODULE=off禁用模块支持,编译时会从GOPATH和vendor文件中查找包。
  2. GO111MODULE=on启用模块支持,编译时会忽略GOPATH和vendor文件夹,只根据go.mod下载依赖。
  3. GO111MODULE=auto,当项目在$GOPATH/src外且项目根目录有go.mod文件时,开启模块支持。

配置命令:

go env -w GOBIN=/Users/用户名/go/bin
go env -w GO111MODULe=on
go env -w GOPOXY=https://goproxy.con,direct //使用七牛云

2.2、GOPOXY的使用

Go Module通过GOPOXY环境变量控制如何使用Go Proxy,GOPROXY是一个Go Proxy站点url列表。

GONOPROXY="https://proxy1.cn,https://proxy2.cn, direct"

上述代码中,direct表示源站(如github),proxy1和proxy2是两个url站点,依赖寻址路径为:优先从proxy1下载依赖,如果proxy1不存在,再从proxy2寻找,如果proxy2不存在,则会回源到源站直接下载依赖,并缓存到Go Proxy站点中。

3、Go Mod的使用

3.1、使用初始化生成go.mod 文件

go mod init 模块名

使用go module管理依赖后会在项目根目录下生成两个文件go.mod和go.sum。go.mod和go.sum是go modules版本管理的指导性文件,因此都应该提交到你的git仓库中,避免其他人使用你写的项目时,重新生成的与你的基准版本不一致。

3.2、go.mod 文件

查看go.mod文件,内容如下:

  • 第一行:当前项目的模块路径
  • 第二行:项目使用的go版本
  • 第三行:require项目所需的直接依赖包及其版本
  • exclude:用于从使用中排除一个特定的模块版本
  • replace:用于将一个包的版本替换为另一个包版本
  • 其中require后的indirect说明这个依赖是非直接依赖

3.3、go.sum文件

go.sum文件就比较复杂了,密密麻麻的。每一行都是由模块路径,模块版本,哈希值组成,其中哈希值是用来保证当前缓存的模块不会被篡改。hash是以h1:开头的字符串,表示生成checksum的算法是第一版的hash算法。

4、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 list -m -json all 以json的方式打印依赖详情
  • go list -m -u all 来检查可以升级的package
  • go get -u need-upgrade-package 升级后会将新的依赖版本更新到go.mod中
  • go get -u 升级所有依赖到最新的版本
  • go get package@verison 更新到指定版本

5、如何给项目添加依赖(写进 go.mod)呢?

  • 在项目中有import,然后go build就会go module自动下载并添加。
  • 自己手工使用go get下载安装后,会自动加入go.mod。