原文链接:http://www.chairis.cn/blog/article/101
美国当地时间2018年8月24日,Go 开发团队宣布推出 Go 1.11 正式版。
此版本增加了对被称作“模块(Go Modules)”的初步支持,这是 GOPATH 的替代方案,集成了对版本控制和软件包分发的支持。
自从Go 1.11 推出之后,一直也没有时间去学习新版本的特性,这次就来研究一下Go Modules的使用吧
安装go 1.11版本后,可以通过以下命令大致看下go mod有哪些命令
go help mod
图中可以看到,go mod的命令语法为
go mod
[arguments]
download
: download modules to local cache (下载依赖的module到本地cache)edit
: edit go.mod from tools or scripts (编辑go.mod文件)graph
: print module requirement graph (打印模块依赖图)init
: initialize new module in current directory (再当前文件夹下初始化一个新的module, 创建go.mod文件)tidy
: add missing and remove unused modules (增加丢失的module,去掉未用的module)vendor
: make vendored copy of dependencies (将依赖复制到vendor下)verify
: verify dependencies have expected content (校验依赖)why
: explain why packages or modules are needed (解释为什么需要依赖)接下来将通过一个简单的项目介绍go mod的使用
首先创建一个空文件夹,用作项目目录
mkdir modtest
然后通过init
命令初始化mod
cd modtest go mod init modtest
上述命令会在modtest目录下生成go.mod
文件。
接下来,我们写一段简单的代码验证一下,在该目录创建main.go文件,写入以下代码:
package main import ( "fmt" ) func main() { fmt.Println("hello word") }
执行以下命令查看结果:
go run main.go
上一步成功创建了项目,接下来,我们要添加一个github的包,这里就简单的添加一个测试的包github.com/Chain-Zhang/modlib
,这个是我自己做的一个及其简单的包,其中就只有一个方法,代码如下:
package modlib
func Message() string {
return "this message from modlib"
}
这里打了个tag:v0.0.1
执行以下命令添加包到项目:
go get -m github.com/Chain-Zhang/[email protected]
从图中可以看到,在go.mod文件中增加了一条内容:
module modtest require github.com/Chain-Zhang/modlib v0.0.1 // indirect
另外又多出一个文件go.sum
github.com/Chain-Zhang/modlib v0.0.1/go.mod h1:vQ6MFJ522Kt0KC6N5sati+nKWd685pu216mW0cW6EMw=
go.mod
则是描述直接依赖包
go.sum
则是描述依赖树锁定
之后我们在项目中调用一下我们modlib的方法试一下,代码如下:
package main import ( "fmt" "github.com/Chain-Zhang/modlib" ) func main() { msg := modlib.Message() fmt.Println(msg) }
执行以下命令,看下效果:
go run main.go // 输出:this message from modlib
这个时候,我们可以尝试下gomod的几个命令
执行最后一个go mod vendor的时候,你会发现,在项目目录里面增加了个目录,vendor,而且,将所依赖的包也放进去了
接下来,我们将modlib加入一段代码,该代码需引用golang.org/x/text
:
package modlib import( "golang.org/x/text/language" "golang.org/x/text/message" "golang.org/x/text/number" ) func Message() string { return "this message from modlib" } func MaxIntegerDigits(){ const year = 1999 p := message.NewPrinter(language.English) p.Println("Year:", number.Decimal(year, number.MaxIntegerDigits(2))) }
并将打上v0.0.2
的tag
然后在项目中调用MaxIntegerDigits方法:
package main import ( "fmt" "github.com/Chain-Zhang/modlib" ) func main() { msg := modlib.Message() fmt.Println(msg) modlib.MaxIntegerDigits() }
在执行以下命令更新包到v0.0.2:
go get github.com/Chain-Zhang/[email protected] // 错误: // go build golang.org/x/text/message: no Go files in // go build golang.org/x/text/number: no Go files in // go build golang.org/x/text/language: no Go files in
这是因为获取golang.org/x/...
时需要,而我这里没有,不过没关系,设置下代理即可:
// bash mac export GOPROXY=https://goproxy.io
// powershell windows $env:GOPROXY = "https://goproxy.io"
然后再执行命令:
go get github.com/Chain-Zhang/[email protected]
// go: finding golang.org/x/text/message latest
// go: finding golang.org/x/text/language latest
// go: finding golang.org/x/text/number latest
成功之后go.mod及go.sum的变化:
// go.mod
module modtest
require (
github.com/Chain-Zhang/modlib v0.0.2
golang.org/x/text v0.3.0 // indirect
)
// go.sum
github.com/Chain-Zhang/modlib v0.0.2 h1:Rj839yAnYX7yER2s28+92fDTkOTRqjr2AJIZ4vqTvRk=
github.com/Chain-Zhang/modlib v0.0.2/go.mod h1:vQ6MFJ522Kt0KC6N5sati+nKWd685pu216mW0cW6EMw=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
这个时候我们把版本再回到v0.0.1
go get github.com/Chain-Zhang/[email protected]
这个时候因为我们调用了v0.0.2的modlib.MaxIntegerDigits方法,所以会报错,只要删掉就可以了。
但是在我们的go.mod中却有个多余的引用,即golang.org/x/text
,因为v0.0.1中没有用到该包。
此时我们就可以执行go mod tidy
来清除不必要的引用,和添加丢失的引用。执行之后,go.mod文件中对于golang.org/x/text
的引用就不见了。
获取依赖的特定版本,用来升级和降级依赖。可以自动修改 go.mod文件,而且依赖的依赖版本号也可能会变。
与以前不同的是,新版 go get可以在末尾加 @符号,用来指定版本。
它要求仓库必须用 v1.2.0格式打 tag,像 v1.2
少个零都不行的,必须是语义化的、带 v前缀的版本号。
eg:
go get github.com/gorilla/mux # 匹配最新的一个 tag go get github.com/gorilla/mux@latest # 和上面一样 go get github.com/gorilla/[email protected] # 匹配 v1.6.2 go get github.com/gorilla/mux@e3702bed2 # 匹配 v1.6.2 go get github.com/gorilla/mux@c856192 # 匹配 c85619274f5d go get github.com/gorilla/mux@master # 匹配 master 分支
go build -mod=readonly
防止隐式修改 go.mod,如果遇到有隐式修改的情况会报错,可以用来测试 go.mod 中的依赖是否整洁,但如果明确调用了 go mod、go get 命令则依然会导致 go.mod 文件被修改。
go build -mod=vendor
在开启模块支持的情况下,用这个可以退回到使用 vendor 的时代。