目录
文章目录
- 目录
- go mod 依赖包管理
- 使用 go mod
go mod 依赖包管理
go mod 是 Golang 1.11 版本引入的依赖包管理工具。其中,Golang 对 Modules 的定义:Modules 是相关 Go Packages 的集合,是源代码交换和版本控制的单元。
go 指令支持使用 Modules,包括记录和解析对其他模块的依赖性。Go Modules 替换旧的基于 GOPATH 的依赖管理方式,不再需要包含例如:src,bin 这样的子目录,一个源代码目录甚至是空目录都可以作为 Modules,只要其中包含了 go.mod 文件。
go.mod 文件一旦创建后,它的内容将会被 go toolchain 全面掌控。go toolchain 会在各类命令执行时,比如:go get、go build、go mod 等修改和维护 go.mod 文件。使用 go.mod 方式管理的依赖包都被下载到了 $GOPATH/pkg/mod 目录:
$ ll $GOPATH/pkg/mod/
total 0
drwxr-xr-x 3 mickeyfan staff 96B 7 12 17:50 9fans.net
drwxr-xr-x 4 mickeyfan staff 128B 7 12 18:05 cache
drwxr-xr-x 69 mickeyfan staff 2.2K 7 12 18:12 github.com
dr-x------ 16 mickeyfan staff 512B 7 12 17:51 go.starlark.net@v0.0.0-20190702223751-32f345186213
drwxr-xr-x 3 mickeyfan staff 96B 7 12 17:49 golang.org
drwxr-xr-x 6 mickeyfan staff 192B 7 12 17:52 gopkg.in
drwxr-xr-x 3 mickeyfan staff 96B 7 12 17:50 honnef.co
drwxr-xr-x 7 mickeyfan staff 224B 7 12 17:52 mvdan.cc
drwxr-xr-x 3 mickeyfan staff 96B 7 12 17:52 sourcegraph.com
除了 go.mod 之外,go 指令还维护了一个 go.sum 文件,其中包含特定模块版本内容的加密哈希。go 指令使用 go.sum 文件来确保这些模块的哈希值,以确保项目所依赖的模块不会出现意外更改。go.mod 和 go.sum 都应该应用于版本控制。 并且 go.sum 不需要手工维护,所以可以不用太关注。
使用 go mod
使用 Go Modules 需要配置 GO111MODULE 环境变量,GO111MODULE 有三个值:off、on 和 auto(默认值):
- GO111MODULE=off:go 指令不支持 Modules 功能,寻找依赖包的方式依旧沿用旧版本那种通过 vendor 目录或者 GOPATH 环境变量来查找。
- GO111MODULE=on:go 指令使用 Modules 方式,而不再到 GOPATH 目录下查找依赖包。
- GO111MODULE=auto:go 指令根据当前目录来决定是否启用 Modules 功能。这种情况下可以分为两种情形:
- 当项目处于 GOPATH/src 内,则会使用 GOPATH/src 的依赖包。
- 当项目处于 GOPATH/src 外,则使用 go.mod 里 require 声明的包。
建议开启:
export GO111MODULE=on
使用 go.mod 的流程:
首先要在 GOPATH/src 目录之外新建 Golang 项目。
创建 main:
package main
import "fmt"
func main() { fmt.Println("hello world!") }
初始化项目的 go.mod
$ go mod init hello
module hello
go 1.14
注意,项目下属的子目录是不需要再次 init 的,所有子目录里的依赖都会组织在根目录的 go.mod 文件里。
导入外部包:
package main
import ( "fmt" "github.com/gohouse/gorose" )
func main() { fmt.Println("hello world!") }
运行程序:
$ go run hello.go go: finding module for package github.com/gohouse/gorose go: downloading github.com/gohouse/gorose v1.0.5 go: found github.com/gohouse/gorose in github.com/gohouse/gorose v1.0.5 go: finding module for package github.com/gohouse/converter go: downloading github.com/BurntSushi/toml v0.3.0 go: downloading github.com/gohouse/converter v0.0.3 go: found github.com/gohouse/converter in github.com/gohouse/converter v0.0.3 go: downloading github.com/go-sql-driver/mysql v1.4.0
command-line-arguments
./hello.go:5:5: imported and not used: "github.com/gohouse/gorose"
检查 go.mod 自动依赖清单维护
module hello
go 1.14
require ( github.com/gohouse/converter v0.0.3 // indirect github.com/gohouse/gorose v1.0.5 // indirect )
其中 require 是一个关键字,此外还有 module、replace 和 exclude:
- module 语句:指定包的名字(路径)。
- require 语句:指定的依赖项模块。
- replace 语句:可以替换依赖项模块。
- exclude语句:可以忽略依赖项模块。
另外,上述的 v0.0.3 就是依赖包 converter 的版本。如果没有在 go.mod 指定版本,go 指令就会自动下载代码中的依赖的最新版本。否则,go 指令会根据 require 语句的路径和版本进行下载。指定版本时也可以用 latest,表示下载最新的版本。
replace 语句常用于依赖包实际路径变更的场景中,例如:
replace golang.org/x/text => github.com/golang/text latest
如此的,在这种情况下依赖包的维护会变得更简单。
还需要注意 go.mod 中的 module hello
这一条语句,因为当前项目已经不在 GOPATH/src 内了,所以 module hello
标注了项目 “根” 的路径,以此来作为项目中其他包的根路径。
同时,go mod 指令也提供了以下子指令:
初始化一个 moudle
go mod init
下载 modules 到本地 Cache
go mod download
注:目前所有模块版本数据均缓存在 GOPATH/pkg/mod 和 GOPATH/pkg/sum 下。
编辑 go.mod 文件,选项有 -json、-require 和 -exclude
go mod edit
e.g.
go mod edit -replace=golang.org/x/crypto@v0.0.0=github.com/golang/crypto@latest
以文本模式打印模块需求图
go mod graph
删除错误或者不使用的 modules
go mod tidy
生成 vendor 目录
go mod vendor
验证依赖是否正确
go mod verify
查找依赖
go mod why
清理 modules 缓存
go clean -modcache