为了解决Go包管理的问题,Go从1.11开始加入了Go Modules这一新特性。让包的依赖和版本管理更加容易。golang
一个module
能够理解为一个单独的包或者模块,module
的根目录下会包含一个go.mod
文件。go.mod
文件中定义了该module
被其它包import
的path
,同时也包含了该module
中依赖哪些包,和这些包的版本号。ui
Go 1.11须要设置GO111MODULE来开启module功能 GO111MODULE=on,会开启使用module GO111MODULE=auto默认值,会根据当前目前来决定是否开启module。若是当前目录在``GOPATH/src``以外且当前目录有``go.mod``文件或当前文件在包含go.mod文件的目录下面 从Go 1.13开始module被默认开启
在非GOPATH/src
目录下建立一个空文件夹hello
,而后在文件夹下建立hello.go
文件:code
package hello func Hello() string { return "Hello, world." }
写一个单测文件hello_test.go
:ip
package hello import "testing" func TestHello(t *testing.T) { want := "Hello, world." if got := Hello(); got != want { t.Errorf("Hello() = %q, want %q", got, want) } }
运行go test命令,这个时候返回:get
PS D:\Code\hello> go test PASS ok _/D_/Code/hello 0.176s
能够看到当前的目录是在D:\Code\hello
,不在GOPATH/src
目录下,这时咱们并无建立module,可是go在运行时创造了一个假的module名称是:_/D_/Code/hello
qt
接下来运行go mod init
命令,建立一个module而且运行单测:string
go mod init example.com/hello go: creating new go.mod: module example.com/hello go test PASS ok example.com/hello 0.177s
能够看到case运行经过,而且返回ok example.com/hello 0.177s
就是是咱们刚才建立的module。在目录下面也能够看多了一个go.mod
文件它的内容是:hash
module example.com/hello go 1.14
mod
是在module
的根目录下建立的,子目录的import path
是module的path
加上子目录的地址。it
在hello.go文件中导入一个外部的包:io
package hello import "rsc.io/quote" func Hello() string { return quote.Hello() }
运行单测:
go: finding module for package rsc.io/quote go: found rsc.io/quote in rsc.io/quote v1.5.2 --- FAIL: TestHello (0.00s) hello_test.go:8: Hello() = "你好,世界。", want "Hello, world." PASS ok example.com/hello 0.177s
这时打开go.mod
文件:
module example.com/hello go 1.14 require rsc.io/quote v1.5.2
能够发现go会自动去找rsc.io/quote
这个依赖的最新版本同时加入到go.mod
文件中,再次运行单测:
PASS ok example.com/hello 0.177s
能够发现go
第二次已经不须要去找rsc.io/quote
。运行go list -m all
返回:
example.com/hello golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c rsc.io/quote v1.5.2 rsc.io/sampler v1.3.0
能够看到引入外部依赖rsc.io/quote
,也会带来它的间接依赖
除了go.mod
文件,目录中也会增长一个go.sum
文件内容以下:
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= rsc.io/quote v1.5.2 h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3Y= rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
后面增长了每一个外部依赖内容的hash值,go经过这些hash值去验证你下载依赖的正确性。
经过上面的go list -m all
能够看到 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
咱们用到的版本是v0.0.0-20170915032832-14c0d48ead0c
。咱们接下来升级它的版本:
go get golang.org/x/text go: golang.org/x/text upgrade => v0.3.3 go: downloading golang.org/x/text v0.3.3 go test PASS ok example.com/hello 0.199s
此时go.mod
文件内容是:
module example.com/hello go 1.14 require ( golang.org/x/text v0.3.3 // indirect rsc.io/quote v1.5.2 )
能够看到golang.org/x/text v0.3.3 // indirect
这个间接依赖已经被升级到v0.3.3
了。
运行go list -m all
返回:
example.com/hello golang.org/x/text v0.3.3 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e rsc.io/quote v1.5.2 rsc.io/sampler v1.3.0
运行go mod tidy
能够删除没有使用的包
go mod vendor
会下载依赖到vendor中,只会下载你代码中的依赖,不会下载全部go.mod中引用的依赖
打开老项目的目录通常是在GOPATH/src
下面,而后运行
go mod init xxx go build
须要注意的是迁移项目可能会出现包冲突的问题,会报相似
cannot load xxxx: ambiguous import: found xxxx in multiple modules:
这样的错误,这时可能须要再go.mod中手动指定这个包的版本号