golang学习笔记-go mod的使用
1.go modules的基本介绍
1.1 环境变量
export GO111MODULE="on"
export GOPATH="/home/go-project/"
export GOPROXY="https://goproxy.cn,direct"
export GONOPROXY="git.example.com,x1"
export GONOSUMDB="git.example.com,x1"
export GOPRIVATE="git.example.com,x1"
export GOSUMDB="sum.golang.org"
1) GO111MODULE
go语言提供GO111MODULE
环境变量三个值,用于GO111MODULE
的开关:
- auto:只要项目中包含了
go.mod
这个文件,就启动该项目的go modules,在 Go1.11 至 Go1.14 中仍然是默认值。 - on:启动
go modules
- off:关闭
go modules
2) GOPROXY
go env
中默认的代理是 GOPROXY="https://proxy.golang.org,direct" ,但是在国内是无法访问的,这里需要设置成国内的代理地址 GOPROXY="https://goproxy.cn,direct"
GOPROXY
的值是一个以英文逗号 “,” 分割的 Go 模块代理列表,允许设置多个模块代理,假设你不想使用,也可以将其设置为 “off” ,这将会禁止 Go 在后续操作中使用任何 Go 模块代理。
direct
实际上 “direct” 是一个特殊指示符,用于指示 Go 回源到模块版本的源地址去抓取(比如 GitHub 等),场景如下:当值列表中上一个 Go 模块代理返回 404 或 410 错误时,Go 自动尝试列表中的下一个,遇见 “direct” 时回源,也就是回到源地址去抓取,而遇见 EOF 时终止并抛出类似 “invalid version: unknown revision…” 的错误。
3)GONOPROXY、GONOSUMDB、GOPRIVATE
这三个环境变量都是用在当前项目依赖了私有模块,例如像是你公司的私有 git 仓库,又或是 github 中的私有库,都是属于私有模块,都是要进行设置的,否则会拉取失败。对于一些自己的私有模块代码,需要在GOPRIVATE
上设置,在拉取时会提示输入用户名和密码。
可以设置多个,用英文的逗号分隔开;或者用通配符等
export GOPRIVATE="git.example.com,github.com/eddycjy/mquote"
export GOPRIVATE="*.example.com" # 通配example.com的域名
1.2 提供的命令
在go环境的shell中执行 go mod help 查看命令和说明。
Usage: go mod <command> [arguments] The commands are: download 下载模块到本地缓存,缓存路径是$GOPATH/pkg/mod/cache
edit 是提供了命令版编辑go.mod
的功能,例如go mod edit -fmt go.mod
会格式化go.mod
graph 把模块之间的依赖图显示出来 init 初始化模块(例如把原本dep管理的依赖关系转换过来) tidy 增加缺失的包,移除没用的包 vendor 把依赖拷贝到vendor/
目录下 verify 确认依赖关系 why 解释为什么需要包和模块2.go modules的基本使用
2.go modules的基本使用
开启go modules
后,就可以创建项目并且生成mod文件,来管理项目的所有依赖了。以下是go env
环境的配置:
GO111MODULE="auto" GOARCH="amd64" GOBIN="/go/bin/" GOCACHE="/root/.cache/go-build" GOENV="/root/.config/go/env" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="linux" GOINSECURE="" GONOPROXY="" GONOSUMDB="" GOOS="linux" GOPATH="/home/go-project/" GOPRIVATE="" GOPROXY="https://goproxy.cn,direct" GOROOT="/go" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/go/pkg/tool/linux_amd64" GCCGO="gccgo" AR="ar" CC="gcc" CXX="g++" CGO_ENABLED="1" GOMOD="" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build940953411=/tmp/go-build -gno-record-gcc-switches"
设置了GOPATH
为 /home/go-project/ ,并且代理指向了国内的代理地址,防止国外镜像无法访问的情况。
2.1 初始化项目
在$GOPATH
目录下创建一个新的项目example.com/mycount/hello
,example.com
模拟github.com,mycount
模拟账号,hello
是最终的项目名称。目录和文件结构:
2.1.1 初始化.mod文件
在hello
目录下执行 go mod init example.com/mycount/hello 初始化hello项目的mod文件,如下:
执行完初始化操作后生成了一个go.mod的文件,里面只记录了2行:
- module:用于定义当前项目的模块路径
- go:用于标识当前模块的 Go 语言版本,值为初始化模块时的版本,目前来看还只是个标识作用
2.1.2 简单一个示例
在hello
目录下写一个main.go
的文件,里面用了一个第三方的库。
package main import ( "net/http" "github.com/gin-gonic/gin" "github.com/json-iterator/go" ) type resp struct { Status int `json:"status"` Message string `json:"message"` } func main() { router := gin.Default() router.GET("/", hello()) if err := router.Run(":6060"); err != nil { panic(err) } } func hello() gin.HandlerFunc { return func(context *gin.Context) { strResp, _ := jsoniter.MarshalToString(resp{ Status: http.StatusOK, Message: "success", }) context.String(http.StatusOK, strResp) } }
在hello
目录下执行go get
命令,拉取依赖库:
拉取依赖之后生成了一个go.mod和go.sum文件,go.mod文件:
go.sum的内容:
同时在$GOPATH
目录下多了一个pkg文件,里面有拉取的文件依赖。这个文件是一个全局的缓存。
2.1.3 go modules的go get
在拉取项目依赖时,你会发现拉取的过程总共分为了三大步,分别是 finding(发现)、downloading(下载)以及 extracting(提取), 并且在拉取信息上一共分为了三段内容:
需要注意的是,所拉取版本的 commit 时间是以UTC时区为准,而并非本地时区,同时我们会发现我们 go get 命令所拉取到的版本是 v0.0.0,这是因为我们是直接执行 go get -u 获取的,并没有指定任何的版本信息,由 Go modules 自行按照内部规则进行选择。
那么我想选择具体版本应当如何执行呢,如下: