背景介绍

gomod 是官方在go1.11推出的包管理器,并且从Go1.13版本开始,gomod是Go语言默认的依赖管理工具。

首先我们得了解一下,在引入gomod前,Go中包导入的顺序:

  1. 首先查看当前目录有无vendor目录,如果有,先搜寻vendor中;
  2. 然后去GOROOT中搜寻;
  3. 最后去GOPATH中搜寻;

这也是为什么你的项目一定是要放在GOPATH中。而引入了gomod之后,流程就不一样了。开启gomod后,所有的依赖包会存放在GOPATH/pkg下面,所以多个项目都可以共享同一份,而不用每个项目拉取一份。

使用方法

配置

主要是有几个环境变量:

GO111MODULE

就是gomod的开关

  • off

    关闭gomodule功能,流程与原来一致。

  • on

    go命令行会使用modules,并且不会去GOPATH目录下查找。

  • auto

    默认值,go命令行将会根据当前目录来决定是否启用module功能。这种情况下可以分为两种情形:

    • 当前目录在GOPATH/src之外且该目录包含go.mod文件
    • 当前文件在包含go.mod文件的目录下面。

GOPROXY

配置的代理,由于众所周知的原因,想访问一些仓库访问不到,就得走代理配置了

  • <url>[,<url>][,direct]

    默认值是https://proxy.golang.org,direct,配置多个会依次去寻找,最后的direct则是如果都没找到就去源地址

  • 置空则是不走代理

GOPRIVATE

配置在这里的表示是私有仓库,不会走proxy下载也不会做校验

  • <url>[,<url>]

    举个例子

    1
    GOPRIVATE=*.corp.example.com,rsc.io/private

    就是git.corp.example.com abc.corp.example.com rsc.io/private rsc.io/private/abc 都不会走proxy下载也不会做校验了

GOSUMDB

在对依赖进行变动(更新/添加)操作时会自动维护一个go.sum,然后去这个服务器做校验,防止模块被篡改。

  • <db_name>+<publickey>+<url>

    默认值是 sum.golang.org,这是google的校验服务器,下面这几种写法都可

    1
    2
    3
    GOSUMDB="sum.golang.org"
    GOSUMDB="sum.golang.org+<publickey>"
    GOSUMDB="sum.golang.org+<publickey> https://sum.golang.org"

    因为对于 http://sum.golang.org,Go 自己知道其对应的 publickey 和 url,所以我们只要配置一个名字即可。除此之外的,都需要指明 publickey,url 默认是 https://\

  • off

    关闭校验,国内基本只能关闭了

GONOSUMDB

关闭校验的部分

  • <url>[,<url>]

    举个例子

    1
    GONOSUMDB=*.corp.example.com,rsc.io/private

    就是git.corp.example.com abc.corp.example.com rsc.io/private rsc.io/private/abc 都不会做校验了

常用命令

go mod init

初始化仓库,会在当前目录创建一个go.mod

go mod download

下载当前go.mod中的依赖

go mod edit

编辑go.mod,具体可以查看go help mod edit

go mod tidy

检查依赖,删除有问题的或者无用的依赖,下载没有的依赖

go mod vendor

生成vendor目录并将依赖放入其中

go mod verify

校验依赖

go mod why

查看依赖原因

go.mod

这里我们看一个go.mod示例

1
2
3
4
5
6
7
8
9
10
11
12
13
module example.com/test

require (
golang.org/x/test1 v0.3.0
gopkg.in/x/test2 v2.1.0 // indirect
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a // indirect
test v0.0.1
)

replace (
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a => github.com/golang/crypto v0.0.0-20190313024323-a1f597ede03a
test => ../test
)

里面一共分3块

module

最开始的module表示的是本模块路径。

module

表示的是依赖的模块

第一项为路径

第二项为版本,go module 安装 package 的原則是先拉最新的 release tag,若无tag则拉最新的commit,所以会有crypto后面的这种版本格式,

后面的注释indirect则代表是间接引用,没有则是直接引用

replace

这里可以将某些get不到的库替换成别的位置的库或者本地的库

子模块

举个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
go-test

├── go.mod
├── test
│ └── test1
│ └── test2
│ └── test3
│ ├── a.go
│ └── go.mod
├── test1
│ └── a.go
└── test2
├── b.go
└── go.mod

这么一个结构如果想按tag引入的话怎么引入?

1
2
3
4
5
6
7
8
9
10
11
12
//引入v0.0.1的go-test
git tag v0.0.1
go get github.com/SVz777/go-test@v0.0.1

//引入v0.0.1的go-test/test2
git tag test2/v0.0.1
go get github.com/SVz777/go-test/test2@v0.0.1

//引入v0.0.1的go-test/test/test1/test2/test3
git tag test/test1/test2/test3/v0.0.1
go get github.com/SVz777/go-test/test/test1/test2/test3@v0.0.1

也就是tag得打成对应module的相对路径@版本号

go工具链

go get

go get做的操作都会同步影响到go.mod

go build / go run

如果发现依赖不存在会先去下载