Go 1.11 前天已經正式發布了,這個版本包含了兩個最重要的feature就是 module
和web assembly
。雖然也有一些簡單的教程介紹了go module
的特性,但是基本上都是hello world
的例子,在實踐的過程中, 很多人都在“拚命的掙紮”,包括我自己, 從一些qq群、github的issue, twitter上都可以看到大家茫然或者抱怨的語句。
雖然有三個協助檔案go help mod
、go help modules
、go help module-get
可以瞭解一些go module的用法,但是感覺Go開發組對module
這一特性還是沒有很好的做一個全面的介紹,很多情況還得靠大家看原始碼或者去猜,比如module下載的檔案夾、版本格式的完整聲明,module
的最佳實務等,並且當前Go 1.11的實現中還有一些bug,給大家在使用的過程中帶來了很大的困難。
我也在摸索中前行, 記錄了摸索過程中的一些總結,希望能給還在掙紮中的Gopher一些協助。
Introduction to Go Modules 是一篇很好的go module 入門介紹, 如果你仔細閱讀了它,應該就不需要看本文了。
GO111MODULE
要使用go module
,首先要設定GO111MODULE=on
,這沒什麼可說的,如果沒設定,執行命令的時候會有提示,這個大家應該都瞭解了。
既有項目
假設你已經有了一個go 項目, 比如在$GOPATH/github.com/smallnest/rpcx
下, 你可以使用go mod init github.com/smallnest/rpcx
在這個檔案夾下建立一個空的go.mod
(只有第一行 module github.com/smallnest/rpcx
)。
然後你可以通過 go get ./...
讓它尋找依賴,並記錄在go.mod
檔案中(你還可以指定 -tags
,這樣可以把tags的依賴都尋找到)。
通過go mod tidy
也可以用來為go.mod
增加丟失的依賴,刪除不需要的依賴,但是我不確定它怎麼處理tags
。
執行上面的命令會把go.mod
的latest
版本換成實際的最新的版本,並且會產生一個go.sum
記錄每個依賴庫的版本和雜湊值。
新的項目
你可以在GOPATH
之外建立新的項目。
go mod init packagename
可以建立一個空的go.mod
,然後你可以在其中增加require github.com/smallnest/rpcx latest
依賴,或者像上面一樣讓go自動探索和維護。
go mod download
可以下載所需要的依賴,但是依賴並不是下載到$GOPATH
中,而是$GOPATH/pkg/mod
中,多重專案可以共用快取的module。
go mod命令
12345678 |
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 (解釋為什麼需要依賴) |
有些命令還有bug, 比如go mod download -dir
:
1234 |
go mod download -dir /tmpflag provided but not defined: -dirusage: go mod download [-dir] [-json] [modules]Run 'go help mod download' for details. |
協助裡明明說可以設定dir
,但是實際卻不支援dir
參數。
看這些命令的協助已經比較容易瞭解命令的功能。
翻牆
在國內訪問golang.org/x
的各個包都需要翻牆,你可以在go.mod
中使用replace
替換成github上對應的庫。
12345 |
replace (golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac => github.com/golang/crypto v0.0.0-20180820150726-614d502a4dacgolang.org/x/net v0.0.0-20180821023952-922f4815f713 => github.com/golang/net v0.0.0-20180826012351-8a410e7b638dgolang.org/x/text v0.3.0 => github.com/golang/text v0.3.0) |
依賴庫中的replace
對你的主go.mod
不起作用,比如github.com/smallnest/rpcx
的go.mod
已經增加了replace
,但是你的go.mod
雖然require
了rpcx
的庫,但是沒有設定replace
的話, go get
還是會訪問golang.org/x
。
所以如果想編譯那個項目,就在哪個項目中增加replace
。
版本格式
下面的版本都是合法的:
12345 |
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7gopkg.in/vmihailenco/msgpack.v2 v2.9.1gopkg.in/yaml.v2 <=v2.2.1github.com/tatsushid/go-fastping v0.0.0-20160109021039-d7bb493dee3elatest |
go get 升級
- 運行
go get -u
將會升級到最新的次要版本或者修訂版本(x.y.z, z是修訂版本號碼, y是次要版本號碼)
- 運行
go get -u=patch
將會升級到最新的修訂版本
- 運行
go get package@version
將會升級到指定的版本號碼version
go mod vendor
go mod vendor
會複製modules下載到vendor中, 貌似只會下載你代碼中引用的庫,而不是go.mod中定義全部的module。
go module, vendor 和 Travis CI
https://arslan.io/2018/08/26/using-go-modules-with-vendor-support-on-travis-ci/