go module學習筆記


go module了解

前言

Go 的包管理方式是逐漸演進的, 最初是 monorepo 模式,所有的包都放在 GOPATH 里面,使用類似命名 空間的包路徑區分包,不過這種包管理顯然是有問題,由於包依賴可能會引入破壞性更新,生產環境和測試環 境會出現運行不一致的問題。

從 v1.5 開始開始引入 vendor 包模式,如果項目目錄下有 vendor 目錄,那么 go 工具鏈會優先使 用 vendor 內的包進行編譯、測試等,這之后第三方的包管理思路都是通過這種方式來實現,比如說由社區 維護准官方包管理工具 dep。

不過官方並不認同這種方式,在 v1.11 中加入了 Go Module 作為官方包管理形式,就這樣 dep 無奈的 結束了使命。最初的 Go Module 提案的名稱叫做 vgo,下面為了介紹簡稱為 gomod。不過在 v1.11 和 v1.12 的 Go 版本中 gomod 是不能直接使用的。可以通過 go env 命令返回值的 GOMOD 字段是否為空 來判斷是否已經開啟了 gomod,如果沒有開啟,可以通過設置環境變量 export GO111MODULE=on 開啟。

哈哈,是時候開始使用go module了

開啟go mod

GO111MODULE 有三個值:

  • on 打開,不會去 GOPATH 下面查找依賴包。
  • off 關閉
  • auto Golang 自己檢測是不是使用 modules 功能。

linux:

export GO111MODULE=on // 開啟
export GO111MODULE=of // 關閉

簡單使用

1、初始化

需要注意的是:我們使用go mod不要在GOPATH目錄下面

我們在GOPATH以為的目錄建立一個項目hello,然后在根目錄下面執行

liz@liz-PC:~/goWork/src/hello$ go mod init hello
go: creating new go.mod: module hello

可以看到go.mod已經生成在了項目的根木下面,然后我們去看下里面的內容

liz@liz-PC:~/goWork/src/hello$ cat go.mod
module hello

go 1.13

發現里面還沒有任何的依賴,因外我們的項目代碼還沒有創建,那么接下來去創建代碼,看看mod如何進行 依賴包的管理,創建hello.go

package hello

import "rsc.io/quote"

func Hello() string {
    return quote.Hello()
}

然后創建testHello.go來測試

package hello

import "testing"

func TestHello(t *testing.T) {
    want := "你好,世界。"
    if got := Hello(); got != want {
        t.Errorf("Hello() = %q, want %q", got, want)
    }
}

因為我們在GOPATH外,所以rsc.io/quote是找不到的。正常執行test找不到這些包,是會報錯的,但是我們 使用go mod這些就不會發生了,那我們執行go test看下

go test
go: finding rsc.io/quote v1.5.2
go: downloading rsc.io/quote v1.5.2
go: extracting rsc.io/quote v1.5.2
go: downloading rsc.io/sampler v1.3.0
go: extracting rsc.io/sampler v1.3.0
go: downloading golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
go: extracting golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
go: finding rsc.io/sampler v1.3.0
go: finding golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
--- FAIL: TestHello (0.00s)
    hello_test.go:8: Hello() = "你好,世界。", want "Hello, world."
FAIL
exit status 1
FAIL    hello   0.003s

發現會主動幫我們下載所需要的依賴包。(go run/test),或者 build(執行命令 go build)的時候都會幫助 我們下載所需要的依賴包。並且這些包都會下載到 $GOPATH/pkg/mod 下面,不同版本並存。

這時候有些包是不能下載的,比如golang.org/x下的包,這時候可以使用代理的方式解決,go也提供了GoProxy 來幫助我們做這些事情,具體看下文GoProxy。

2、依賴升級(降級)

可以使用如下命令來查看當前項目依賴的所有的包。

$ go list -m all
hello
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
rsc.io/quote v1.5.2
rsc.io/sampler v1.3.0

如果我們想要升級(降級)某個package則只需要go get就可以了,比如:

go get package@version

同時我們可以可以查看這個包所支持的版本,選擇合適的進行升級

go list -m -versions package

栗子:
版本查看:

$  go list -m -versions rsc.io/sampler
rsc.io/sampler v1.0.0 v1.2.0 v1.2.1 v1.3.0 v1.3.1 v1.99.99

查看當前的版本:

$ go list -m all
hello
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
rsc.io/quote v1.5.2
rsc.io/sampler v1.3.1

可以發現 rsc.io/sampler 現在的版本是v1.3.1,那么他最高支持的是v1.99.99
版本升級:

$ go get rsc.io/sampler
go: finding rsc.io/sampler v1.99.99
go: downloading rsc.io/sampler v1.99.99
go: extracting rsc.io/sampler v1.99.99

當我們沒有選擇升級的版本,默認的版本就是最高的
升級完成之后我們再來查看當前的版本

$ go list -m all
hello
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
rsc.io/quote v1.5.2
rsc.io/sampler v1.99.99

rsc.io/sampler的版本已經變成了v1.99.99,同樣我們也可以對它的版本進行降級,方法和升級的方法一樣

$ go get rsc.io/sampler@v1.3.1
$ go list -m all
hello
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
rsc.io/quote v1.5.2
rsc.io/sampler v1.3.1

哈哈,已經變成了v1.3.1,降級成功了。

3、更改使用的pkg

讓我們完成使用rsc的轉換。rsc.io/quote 只使用rsc.io/quote/v3。首先我們看下 rsc.io/quote/v3支持的api,因為相比於rsc.io/quote, rsc.io/quote/v3所支持的api可能已經發生了改變。

$ go doc rsc.io/quote/v3
package quote // import "rsc.io/quote"

Package quote collects pithy sayings.

func Concurrency() string
func GlassV3() string
func GoV3() string
func HelloV3() string
func OptV3() string

我們來更新我們的代碼 hello.go

package hello

import "rsc.io/quote/v3"

func Hello() string {
    return quote.HelloV3()
}

然后執行go test

$ go test
go: downloading rsc.io/quote/v3 v3.1.0
go: extracting rsc.io/quote/v3 v3.1.0
PASS
ok      hello   0.003s

發現下載了rsc.io/quote/v3,並且成功運行

4、清除不需要的依賴包

上面我們把rsc.io/quote換成了rsc.io/quote/v3,那么rsc.io/quote就已經不在需要了,這時候我們可以選擇清除掉這些不需要的包

$ go list -m all
hello
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
rsc.io/quote v1.5.2
rsc.io/quote/v3 v3.1.0
rsc.io/sampler v1.3.1
$ cat go.mod
module hello

go 1.13

require (
        rsc.io/quote v1.5.2
        rsc.io/quote/v3 v3.1.0
        rsc.io/sampler v1.3.1 // indirect
)

我們知道go build(test)只會在運行的時候檢查少了那些包,然后進行加載。但是不能確定何時可以安全地刪除某些東西。 僅在檢查模塊中的所有軟 件包以及這些軟件包的所有可能的構建標記組合之后,才能刪除依賴項。普通的build命令不會加載此信息,因此它不能安全地刪除依賴項。
可以使用go mod tidy清除不需要的包

$ go mod tidy
$ go list -m all
hello
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
rsc.io/quote/v3 v3.1.0
rsc.io/sampler v1.3.1
$ cat go.mod
module hello

go 1.13

require (
        rsc.io/quote/v3 v3.1.0
        rsc.io/sampler v1.3.1 // indirect
)
$ go test
PASS
ok      hello   0.003s

GoProxy

proxy 顧名思義,代理服務器。對於國內的網絡環境,有些包是下載不下來的,當然有的人會用梯子去解決。go官方也意識到了這一點,提供了GOPROXY 的方法讓我們下載包。要使用 GoProxy 只需要設置環境變量 GOPROXY 即可。目前公開的 GOPROXY 有:

  • goproxy.io
  • goproxy.cn: 由七牛雲提供,這是一個應屆生發起的項目,好強

當然你也可以實現自己的 GoProxy 服務,比如項目中的依賴包含外部依賴和內部依賴的時候,那么只需要實現 module proxy protocal 協議即可。

值得注意的是,在最新 release 的 Go 1.13 版本中默認將 GOPROXY 設置為 https://proxy.golang.org,這個對於國內的開發者是無法直接 使用的。所以如果升級了 Go 1.13 版本一定要把 GOPROXY 手動改掉。

export GOPROXY=https://goproxy.io

總結

Go 1.11之后的版本都支持go module了, modules 在 Go 1.13 的版本下是默認開啟的。國內使用需要修改GoProxy的代理。
下面是經常使用到的命令:

go mod init 創建初始化go module  
go build, go test 運行的時候就會加載所需要的依賴項
go list -m all 打印檔當前模塊所有的依賴
go get 更改模塊依賴的版本
go mod tidy 刪除不適用的依賴

參考

【Using Go Modules】https://blog.golang.org/using-go-modules
【Go Modules 不完全教程】https://mp.weixin.qq.com/s/v-NdYEJBgKbiKsdoQaRsQg

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM