本文为转载,原文:Golang Module学习使用
介绍
美国当地时间2018年8月24日,Go 开发团队宣布推出 Go 1.11 正式版。
此版本增加了对被称作“模块(Go Modules)”的初步支持,这是 GOPATH 的替代方案,集成了对版本控制和软件包分发的支持。
自从Go 1.11 推出之后,一直也没有时间去学习新版本的特性,这次就来研究一下Go Modules的使用吧
1. go mod 命令
安装go 1.11版本后,可以通过以下命令大致看下go mod有哪些命令
go help mod
图中可以看到,go mod的命令语法为
go mod <command> [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 (解释为什么需要依赖)
2. go mod的使用
接下来将通过一个简单的项目介绍go mod的使用
2.1. 新建项目
首先创建一个空文件夹,用作项目目录
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
2.2. 添加github包
上一步成功创建了项目,接下来,我们要添加一个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/modlib@v0.0.1
执行之后可以看下效果:
从图中可以看到,在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
2.2. 尝试下go mod命令
这个时候,我们可以尝试下gomod的几个命令
执行最后一个go mod vendor的时候,你会发现,在项目目录里面增加了个目录,vendor,而且,将所依赖的包也放进去了
2.3. go mod 翻墙
接下来,我们将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/modlib@v0.0.2
// 错误:
// 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/modlib@v0.0.2
// 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=
2.4. 版本回到v0.0.1
这个时候我们把版本再回到v0.0.1
go get github.com/Chain-Zhang/modlib@v0.0.1
这个时候因为我们调用了v0.0.2的modlib.MaxIntegerDigits方法,所以会报错,只要删掉就可以了。
但是在我们的go.mod中却有个多余的引用,即golang.org/x/text
,因为v0.0.1中没有用到该包。
此时我们就可以执行go mod tidy
来清除不必要的引用,和添加丢失的引用。执行之后,go.mod文件中对于golang.org/x/text
的引用就不见了。
2.5. 其他
2.5.1. go get 命令
获取依赖的特定版本,用来升级和降级依赖。可以自动修改 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/mux@v1.6.2 # 匹配 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 分支
2.5.2. go build 命令
go build -mod=readonly
防止隐式修改 go.mod,如果遇到有隐式修改的情况会报错,可以用来测试 go.mod 中的依赖是否整洁,但如果明确调用了 go mod、go get 命令则依然会导致 go.mod 文件被修改。go build -mod=vendor
在开启模块支持的情况下,用这个可以退回到使用 vendor 的时代。
完
本文为原创,转载请注明出处: Golang Module学习使用