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 一些幫助。
-
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 -m ./...
讓它查詢依賴,並記錄在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 命令
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
:
go mod download -dir /tmp
flag provided but not defined: -dir
usage: go mod download [-dir] [-json] [modules]
Run 'go help mod download' for details.
幫助裡明明說可以設定 dir, 但是實際卻不支援 dir 引數。
看這些命令的幫助已經比較容易瞭解命令的功能。
5. 翻牆
在國內訪問 golang.org/x
的各個包都需要翻牆,你可以在 go.mod
中使用 replace 替換成 github 上對應的庫。
replace (
golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac => github.com/golang/crypto v0.0.0-20180820150726-614d502a4dac
golang.org/x/net v0.0.0-20180821023952-922f4815f713 => github.com/golang/net v0.0.0-20180826012351-8a410e7b638d
golang.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。
6. 版本格式
下麵的版本都是合法的:
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7
gopkg.in/vmihailenco/msgpack.v2 v2.9.1
gopkg.in/yaml.v2 <=v2.2.1
github.com/tatsushid/go-fastping v0.0.0-20160109021039-d7bb493dee3e
latest
7. go get 升級
執行 go get -u
將會升級到最新的次要版本或者修訂版本 (x.y.z, z 是修訂版本號, y 是次要版本號)
執行 go get -u=patch
將會升級到最新的修訂版本
執行 go get package@version
將會升級到指定的版本號 version
8. go mod vendorgo mod vendor
會將 modules 下載到 vendor 中