Go包管理go mod使用
Go Modules介紹
為了解決Go包管理的問題,Go從1.11開始加入了Go Modules這一新特性。讓包的依賴和版本管理更加容易。
一個module
可以理解為一個單獨的包或者模組,module
的根目錄下會包含一個go.mod
檔案。go.mod
檔案中定義了該module
被其它包import
的path
,同時也包含了該module
中依賴哪些包,和這些包的版本號。
Go 1.11需要設定GO111MODULE來開啟module功能 GO111MODULE=on,會開啟使用module GO111MODULE=auto預設值,會根據當前目前來決定是否開啟module。如果當前目錄在``GOPATH/src``之外且當前目錄有``go.mod``檔案或當前檔案在包含go.mod檔案的目錄下面 從Go 1.13開始module被預設開啟
建立一個module
在GOPATH/src
之外建立一個空的資料夾hello
,開啟這個資料夾,建立一個hello.go
檔案:
package hello
func Hello() string {
return "Hello, world."
}
寫一個單測檔案hello_test.go
:
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命令,這個時候返回:
PS D:\Code\hello> go test
PASS
ok _/D_/Code/hello 0.176s
可以看到當前的目錄是在D:\Code\hello
,既不是在GOPATH/src
目錄下,這時也不是一個module,但是go命令創造了一個假的module名稱是:_/D_/Code/hello
我們這時執行go mod init
命令,建立一個module並且執行單測:
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 init
建立了一個go.mod檔案內容是:
module example.com/hello
go 1.14
mod
檔案只需要在module
的根目錄下建立就行了,子目錄的import path
是module的path
加上子目錄的地址。
新增外部依賴
在hello.go檔案中匯入一個外部的包:
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中引用的依賴