Go Modules 使用
Go modules 为 Go 中的官方维护的项目依赖管理解决方案 ,于 Go1.11 正式发布,Go1.14 宣称 ready for production 。
启动 Go Modules
下面两种情况会启动 Go Modules
- go env 中的 GO111MODULE 为 on
- go env 中的 GO111MODULE 为 auto 且项目内有 go.mod 文件
修改 GO111MODULE
go env -w GO111MODULE =auto
初始化模块
使用go mod init [module name]
在当前文件下初始化模块,生成 go.mod 文件。
这里需要注意的是,虽然 Go modules 去除了对 GOPATH 的依赖,但是如果在
GOPATH之外的目录下使用 go mod init 的话, 需要显示加上模块名, 如 go mod init module1 ;而在 GOPATH 下的模块名缺省的话,会自动使用 GOPATH/src 后的文件路径作为模块名。
添加依赖
Go modules 是直接集成在 Go 的工具链中的, 所有添加依赖只需和之前使用 Go 下载模块 工具 go get 即可,并且会在 go.mod 文件内添加下载的模块。
除此之外,还会生成 go.sum 文件,这个文件的作用在于检测依赖模块是否被篡改。
Go modules 会检测下载的包是否在代码中被引用,如果没发现被直接引用的话(即你的项目代码没有 import 这个模块),go.mod 文件内该模块后面会加上 indirect 标识。
使用 go mod tidy 命令会整理项目模块, 如果发现一个依赖模块没有被直接/间接引用的话,会修改 go.mod 文件,去除无关的依赖。
指定版本
指定版本只需要在 go get 模块时带上版本号即可
如go get github.com/gin-gonic/gin@v1.5.0 会指定依赖的版本
更新依赖
跟新依赖的逻辑与 go get 逻辑一致,当 go get 的依赖版本与当前 go.mod 版本内不一致, Go 会自动更新 go.mod 文件。
使用 go get -u 来更新依赖模块的依赖也会被 Go modules 识别并修改 go.mod
下载依赖
如果开启了 Go modules 模式的话, go build / go run 命令都会自动下载依赖且修改 go.mod 文件。
除此之外, 还可以使用 go mod download 下载 go.mod 中的依赖
如何你想把依赖包导入到项目内的 vendor 文件夹的话,可以使用go mod vendor, 这样项目内就会生成包含依赖模块的 vendor 文件夹,带 vendor 发布的话就会少了下载依赖这一步,避免网络导致的编译的问题。
查看依赖
使用go mod graph会列出所有的依赖,不过貌似直接看 go.mod/go.sum 文件也可以达到这个效果。
查看为什么需要这个模块
go mod why <module name> 会列出该模块的被导入的路径,如果不是依赖的的话会显示(main module does not need package <module name>)
代理
GOPROXY
go env 中的 GOPROXY 默认设置了proxy.golang.org, 国内无法正常访问,可以使用
go env -w GOPROXY=https://goproxy.cn,direct 改为国内的镜像代理站点。 GOPROXY 值为逗号分割的列表,direct 的意思是但前面的镜像代理不可用时,回源到模块原地址去拉取, 如github.com/json-iterator/go镜像站点拉取不了时就会到 github 上拉取。
GOPRIVATE
如果下载的包为私有,例如公司建的 git 仓库,镜像站点无法访问, 而又设置了 GOPROXY 不带 direct 的话, go mod 是无法正常使用的。一种方法是在 GOPROXY 加 direct 回源,此外还可以使用 GOPRIVATE 设置不走 GOPROXY 的仓库地址。
如设置了go env -w GOPRIVATE="*.xxx.net"的话, go get xxx.net 子域名的模块就不会走镜像代理。
其他
编辑 go.mod 文件
go mod edit
不过一般场景下貌似没必要使用该功能。
校验模块
go mod verify
校验模块是否被篡改过,应该是结合 go.sum 文件实现的。
从其他依赖管理工具迁移至 Go Modules
非常简单 ,go mod init 就会自动整理依赖,如之前使用 go dep 的话, 会从 Gopkg.lock 文件提取所需要的依赖。当然直接删除别的依赖管理工具文件,直接 go mod init 也是可以的。