跳出Go module的泥潭
★
NEWS
★
? 鳥窩將在今年的 GopherChina 2021大會上分享有關(guān)《深入探索Go Module: 實踐、技巧和陷阱》的主題
說明:go module增在快速的成長中,最近每個版本中(1.11 ~ 1.13)都有很大的變動。建議你閱讀官方的wiki了解go module最新的知識: go/wiki/Modules
最新擴展閱讀(go 1.13):Go module 再回顧。
Go 1.11 前天已經(jīng)正式發(fā)布了,這個版本包含了兩個最重要的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開發(fā)組對module這一特性還是沒有很好的做一個全面的介紹,很多情況還得靠大家看源代碼或者去猜,比如module下載的文件夾、版本格式的完整聲明,module的最佳實踐等,并且當(dāng)前Go 1.11的實現(xiàn)中還有一些bug,給大家在使用的過程中帶來了很大的困難。
我也在摸索中前行, 記錄了摸索過程中的一些總結(jié),希望能給還在掙扎中的Gopher一些幫助。
Introduction to Go Modules 是一篇很好的go module 入門介紹, 如果你仔細(xì)閱讀了它,應(yīng)該就不需要看本文了。
#01
GO111MODULE
要使用go module,首先要設(shè)置GO111MODULE=on,這沒什么可說的,如果沒設(shè)置,執(zhí)行命令的時候會有提示,這個大家應(yīng)該都了解了。
#02
既有項目
假設(shè)你已經(jīng)有了一個go 項目, 比如在$GOPATH/github.com/smallnest/rpcx下, 你可以使用go mod init github.com/smallnest/rpcx在這個文件夾下創(chuàng)建一個空的go.mod (只有第一行 module github.com/smallnest/rpcx)。
然后你可以通過 go get ./...讓它查找依賴,并記錄在go.mod文件中(你還可以指定 -tags,這樣可以把tags的依賴都查找到)。
通過go mod tidy也可以用來為go.mod增加丟失的依賴,刪除不需要的依賴,但是我不確定它怎么處理tags。
執(zhí)行上面的命令會把go.mod的latest版本換成實際的最新的版本,并且會生成一個go.sum記錄每個依賴庫的版本和哈希值。
#03
新的項目
你可以在GOPATH之外創(chuàng)建新的項目。
go mod init packagename可以創(chuàng)建一個空的go.mod,然后你可以在其中增加require github.com/smallnest/rpcx latest依賴,或者像上面一樣讓go自動發(fā)現(xiàn)和維護。
go mod download可以下載所需要的依賴,但是依賴并不是下載到$GOPATH中,而是$GOPATH/pkg/mod中,多個項目可以共享緩存的module。
#02
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 (再當(dāng)前文件夾下初始化一個新的module, 創(chuàng)建go.mod文件))
tidy add missing and remove unused modules (增加丟失的module,去掉未用的module)
vendor make vendored copy of dependencies (將依賴復(fù)制到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.
幫助里明明說可以設(shè)置dir,但是實際卻不支持dir參數(shù)。
看這些命令的幫助已經(jīng)比較容易了解命令的功能。
#05
在國內(nèi)訪問golang.org/x的各個包都需要翻墻,你可以在go.mod中使用replace替換成github上對應(yīng)的庫。
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已經(jīng)增加了replace,但是你的go.mod雖然require了rpcx的庫,但是沒有設(shè)置replace的話,go get還是會訪問golang.org/x。
所以如果想編譯那個項目,就在哪個項目中增加replace。
#06
版本格式
下面的版本都是合法的:
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
#07
go get 升級
運行 go get -u 將會升級到最新的次要版本或者修訂版本(x.y.z, z是修訂版本號, y是次要版本號)
運行 go get -u=patch 將會升級到最新的修訂版本
運行 go get package@version 將會升級到指定的版本號version
#08
go mod vendor
go mod vendor會復(fù)制modules下載到vendor中, 貌似只會下載你代碼中引用的庫,而不是go.mod中定義全部的module。
#09
go module, vendor 和 Travis CI
https://arslan.io/2018/08/26/using-go-modules-with-vendor-support-on-travis-ci/
講師介紹

晁岳攀
20余年的開發(fā)經(jīng)驗。
《Scala集合技術(shù)手冊》作者。
微服務(wù)框架rpcx的作者,rpcx框架被百度、新浪、好未來學(xué)而思、馬蜂窩等大廠使用。
專欄《Go并發(fā)編程實戰(zhàn)課》的作者。
想要加入組織的 Gopher 們,請掃碼入群,即可獲得GopherChina大會的實時動向~
今年2021年GopherChina大會,晁岳攀老師將會帶來《深入探索Go Module: 實踐、技巧和陷阱》內(nèi)容分享,「閱讀原文」即可獲得早鳥票名額。
