歡迎光臨
每天分享高質量文章

跳出Go module的泥潭

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 一些幫助。

  1. GO111MODULE
    要使用 go module, 首先要設置 GO111MODULE=on, 這沒什麼可說的,如果沒設置,執行命令的時候會有提示,這個大家應該都瞭解了。

  2. 既有專案
    假設你已經有了一個 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 記錄每個依賴庫的版本和哈希值。

  3. 新的專案
    你可以在 GOPATH之外創建新的專案。
    go mod init packagename可以創建一個空的 go.mod, 然後你可以在其中增加 require github.com/smallnest/rpcx latest依賴,或者像上面一樣讓 go 自動發現和維護。
    go mod download可以下載所需要的依賴,但是依賴並不是下載到 $GOPATH中,而是 $GOPATH/pkg/mod中,多個專案可以共享快取的 module。

  4. go mod 命令

  1. download    download modules to local cache (下載依賴的module到本地cache))

  2. edit        edit go.mod from tools or scripts (編輯go.mod檔案)

  3. graph       print module requirement graph (打印模塊依賴圖))

  4. init        initialize new module in current directory (再當前檔案夾下初始化一個新的module, 創建go.mod檔案))

  5. tidy        add missing and remove unused modules (增加丟失的module,去掉未用的module)

  6. vendor      make vendored copy of dependencies (將依賴複製到vendor下)

  7. verify      verify dependencies have expected content (校驗依賴)

  8. why         explain why packages or modules are needed (解釋為什麼需要依賴)

有些命令還有 bug, 比如 go mod download -dir:

  1. go mod download -dir /tmp

  2. flag provided but not defined: -dir

  3. usage: go mod download [-dir] [-json] [modules]

  4. Run 'go help mod download' for details.

幫助里明明說可以設置 dir, 但是實際卻不支持 dir 引數。
看這些命令的幫助已經比較容易瞭解命令的功能。

5. 翻牆
在國內訪問 golang.org/x的各個包都需要翻牆,你可以在 go.mod中使用 replace 替換成 github 上對應的庫。

  1. replace (

  2.    golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac => github.com/golang/crypto v0.0.0-20180820150726-614d502a4dac

  3.    golang.org/x/net v0.0.0-20180821023952-922f4815f713 => github.com/golang/net v0.0.0-20180826012351-8a410e7b638d

  4.    golang.org/x/text v0.3.0 => github.com/golang/text v0.3.0

  5. )

依賴庫中的 replace 對你的主 go.mod 不起作用,比如 github.com/smallnest/rpcx的 go.mod 已經增加了 replace, 但是你的 go.mod 雖然 require 了 rpcx 的庫,但是沒有設置 replace 的話, go get 還是會訪問 golang.org/x

所以如果想編譯那個專案,就在哪個專案中增加 replace。

6. 版本格式
下麵的版本都是合法的:

  1. gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7

  2. gopkg.in/vmihailenco/msgpack.v2 v2.9.1

  3. gopkg.in/yaml.v2 <=v2.2.1

  4. github.com/tatsushid/go-fastping v0.0.0-20160109021039-d7bb493dee3e

  5. latest

7. go get 升級
運行 go get -u 將會升級到最新的次要版本或者修訂版本 (x.y.z, z 是修訂版本號, y 是次要版本號)
運行 go get -u=patch 將會升級到最新的修訂版本
運行 go get package@version 將會升級到指定的版本號 version

8. go mod vendor
go mod vendor 會將 modules 下載到 vendor 中

赞(0)

分享創造快樂