go mod详解
一、go mod 是什么
go mod 是 go 1.11 引入的依赖管理工具,之前的 go 中有 package 的概念,go mod 则引入了 module 的概念。 比如在 engine/mai
目录下运行命令 go mod init silverbolt/mai
,在 mai 目录下会生成一个 go.mod 文件, 文件第一行 module silverbolt/mai
就是说当前目录是一个名为 silverbolt/mai
的 module。
二、go mod 要解决什么问题
go mod 可以用来管理 vendor 目录,替换 govendor 这个工具。
使用 go mod,可以在把 go 项目放在任意位置,而不再必须放在 GOPATH 中。
三、go mod 使用
3.1 在项目中使用
进入在任意位置的 go 项目,运行
go mod init [module_name]
命令生成 go.mod运行
go mod tidy
命令添加缺失的 module,移除不再使用的 module运行
go mod download
命令下载依赖 module 到本地 cache(可选)运行
go mod vendor
命令将依赖拷贝一份到当前 module 的 vendor 目录
注:使用 go module 之后,项目目录下的 vendor 目录可以要也可以不要。 go mod 的 cache 位于
$GOPATH/pkg/mod
,没有 vendor 目录编译的时候会使用 cache 下面的依赖。
3.2 添加本地依赖
向 go.mod 中添加本地依赖:
上面中的版本号不能省略,但可以随便写。
四、go mod 的问题
4.1 环境变量 GO111MODULE
使用 go mod 需要将 GO111MODULE 环境变量设为 on 或者 auto。 在 1.11 和 1.12 版本的 go 中,需要 export GO111MODULE=on
, 在 1.13 版本的 go 中,GO111MODULE 被默认置为 auto。
GO111MODULE 为 on 和 off 可以理解为两种不同的模式,两种模式下,一些 go 的命令会有区别。
4.2 go get 命令
4.2.1 GO111MODULE=off 时
在 GO111MODULE=off 的情况下,go get 的功能就是一直使用的那样,下载并安装 package 到 $GOPATH/src 中。
4.2.2 GO111MODULE=on 时
在 GO111MODULE=on 的情况下:
如果当前位于一个 module 中,go get 会下载 package 到 $GOPATH/pkg/mod 也就是 go mod 的 cache 中,
同时会修改 go.mod,把 go get 的 package 添加到当前 module 的依赖中,不管当前 module 实际会不会依赖 go get 的 package。
比如这样:
这里测试 module 的空项目不依赖 gjson,只是在目录下运行了一句 go get,go.mod 中就多了上面这么一行。 当然,再运行一次 go mod tidy,这一行也就被移除了。
关于这一点,golang 的 issues 中的也有一些讨论:链接
4.3 go install 命令
测试目录结构如下
4.3.1 GO111MODULE=off 时
使用 go install ./test_nako
命令可以编译出 test_nako
,并安装可执行文件到 $GOPATH/bin。
4.3.2 GO111MODULE=on 时
如果 test_go_module
目录下没有 go.mod 文件,运行 go install ./test_nako
会提示 go: cannot find main module; see 'go help modules'
错误。
go mod init
命令在 test_go_module
目录下创建 go.mod 文件之后,运行 go install ./test_nako
会提示 go: directory test_nako is outside main module
错误。
只有实际进入 test_nako
目录之后,运行 go install .
目录,才会正确编译出可执行文件并安装到 $GOPATH/bin 目录。
也就是说 GO111MODULE=on 时,只有在 module 的目录下,才能对 module 运行 go install 的命令。
目前看到的 GO111MODULE 环境变量的影响就是这些,可能还会有其他的。
五、总结
go mod 确实要比 GOPATH 更加方便,但是 mod 的 cache 默认在 $GOPATH/pkg/mod 目录下, 为了让项目下载下来之后可以直接编译,项目中还是需要保留 vendor 目录。
如果只是把 go mod 作为 vendor 目录的管理工具引入 Silverbolt,只需要在各个子项目下生成 go.mod 进而生成 vendor 目录即可。
如果在编译时使用 GO111MODULE=on 的模式,源码就不需要在 GOPATH 中编译了,编译工具 terry 那边也需要做较大的修改: 包括为 terry 生成 go.mod、编译时不再拷贝源码、修改编译使用的 install 命令等。
Last updated
Was this helpful?