爲了解決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中手動指定這個包的版本號