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

Golang modules 初探

今天天色剛剛亮起,起床看到 golang 1.11 正式發版了,有著兩個重要的特性:modules 和 WebAssembly。

本博文只要說的是 modules,congJava 轉 golang 的同學肯定是對 golang 的包管理充滿了無奈之情,我也曾在部落格中介紹過 glide,也介紹過 dep,現在我們再一次升級介紹 modules。

什麼是 modules

現在都在說 modules,那麼它是什麼? 
到檔案看看 Modules, module versions, and more:

  1. A module is a collection of related Go packages. Modules are the unit of source code interchange and versioning. The go command has direct support for working with modules, including recording and resolving dependencies on other modules. Modules replace the old GOPATH-based approach to specifying which source files are used in a given build.

翻譯一下:

  1. 模組是相關Go包的集合。modules是原始碼交換和版本控制的單元。 go命令直接支援使用modules,包括記錄和解析對其他模組的依賴性。modules替換舊的基於GOPATH的方法來指定在給定構建中使用哪些源檔案。

可以得到兩個重要資訊:

  • Go 命令列支援 modules 操作

  • modules 用來替換 GOPATH 的

大家不需要太擔心了,golang 1.11 版本僅僅是指對 modules 的初步支援,之前老的 GOPATH 還是可以繼續使用的,有人說是在 golang 1.12 去除,但是我覺得有點早了,畢竟人的慣性不是這麼容易改變的。

如何使用 modules

modules 是一個新的特性,那麼就需要新的 Golang 版本進行支援了,可以到官網下載,一定要是 go 1.11 及以上的版本(寫博文的時候 go 1.11 剛剛出來)。
這麼部署就在這裡說了,相信初學者也是知道怎麼做的。

還有人記得 vendor 剛剛出來時候 golang 提供的環境變數 GO15VENDOREXPERIMENT嗎?現在 modules 出來,按照慣例也提供了一個環境變數 GO111MODULE,這個變數的三個 1 太有魔性了。

GO111MODULE

GO111MODULE可以設定為三個字串值之一:off,on 或 auto(預設值)。

  • off,則 go 命令從不使用新模組支援。它查詢 vendor 目錄和 GOPATH 以查詢依賴關係; 也就是繼續使用 “GOPATH 樣式”。

  • on,則 go 命令需要使用模組,go 會忽略 GOPATH 和 vendor 檔案夾,只根據 go.mod 下載依賴。

  • auto 或未設定,則 go 命令根據當前目錄啟用或禁用模組支援。僅噹噹前目錄位於 GOPATH/src 之外並且其本身包含 go.mod 檔案或位於包含 go.mod 檔案的目錄下時,才啟用模組支援。

Defining a module

開始的時候誰也不知道怎麼使用?不過 go 已經給我提供了工具了,可以在控制檯輸入:

  1. go help modules

看到一大串的檔案輸出,看著都頭疼了,一會兒我們再簡要說明重點,現在先進行操作。

  1. qiang@DESKTOP-2A835P9 MINGW64 /d/code/gopath/src/gitlab.luojilab.com/zeroteam/ddkafka (module)

  2. $ export GO111MODULE=on  #開啟modules

  3. qiang@DESKTOP-2A835P9 MINGW64 /d/code/gopath/src/gitlab.luojilab.com/zeroteam/ddkafka (module)

  4. $ go mod init  gitlab.luojilab.com/zeroteam/ddkafka # 建立go.mod

  5. go: creating new go.mod: module gitlab.luojilab.com/zeroteam/ddkafka

  6. qiang@DESKTOP-2A835P9 MINGW64 /d/code/gopath/src/gitlab.luojilab.com/zeroteam/ddkafka (module)

  7. $ ls    # 真的建立了,google大法好呀

  8. README.md  go.mod  models.go  mq_interface.go  sarama  segmentio

  9. qiang@DESKTOP-2A835P9 MINGW64 /d/code/gopath/src/gitlab.luojilab.com/zeroteam/ddkafka (module)

  10. $ cat go.mod    # 看看裡面什麼東西

  11. module gitlab.luojilab.com/zeroteam/ddkafka

  12. qiang@DESKTOP-2A835P9 MINGW64 /d/code/gopath/src/gitlab.luojilab.com/zeroteam/ddkafka (module)

  13. $ cd segmentio/

  14. qiang@DESKTOP-2A835P9 MINGW64 /d/code/gopath/src/gitlab.luojilab.com/zeroteam/ddkafka/segmentio (module)

  15. $ go test   # 執行一下看看

  16. go: finding github.com/segmentio/kafka-go latest

  17. go: finding github.com/golang/glog latest

  18. go: downloading github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b

  19. go: downloading github.com/segmentio/kafka-go v0.0.0-20180716203113-48c37f796910

  20. qiang@DESKTOP-2A835P9 MINGW64 /d/code/gopath/src/gitlab.luojilab.com/zeroteam/ddkafka/segmentio (module)

  21. $ go list -m

  22. gitlab.luojilab.com/zeroteam/ddkafka

細心的同學一定可以發現,執行 go mod init [module]使用 go.mod只有一行資訊 module gitlab.luojilab.com/zeroteam/ddkafka,在執行 go build、 go test、 go list 命令時會根據需要的依賴自動生成 require 陳述句。

現在來說說如何定義一個 modules,modules 是由 Go 源檔案目錄結構定義的,如果目錄下含有 go.mod 檔案,該目錄稱為模組根目錄(module root)。模組根目錄及其子目錄所有的 Go 包都是屬於該 modules 的,但是如果子目錄包含有了自己的 go.mod 檔案就隸屬於該 modules。
舉一個例子:

  1. qiang@DESKTOP-2A835P9 MINGW64 /d/code/gopath/src/gitlab.luojilab.com/zeroteam/ddkafka (module)

  2. $ tree

  3. .

  4. |-- README.md

  5. |-- go.mod

  6. |-- go.sum

  7. |-- models.go

  8. |-- mq_interface.go

  9. |-- sarama

  10. |   |-- sarama_consumer.go

  11. |   |-- sarama_consumer_test.go

  12. |   |-- sarama_producer.go

  13. |   `-- sarama_producter_test.go

  14. `-- segmentio

  15.    |-- segmention_Consumer.go

  16.    |-- segmention_consumer_test.go

  17.    |-- segmention_producer.go

  18.    `-- segmention_producter_test.go

gitlab.luojilab.com/zeroteam/ddkafka目錄下含有了 go.mod 檔案,所以其子目錄 sarama和 segmentio都屬於 gitlab.luojilab.com/zeroteam/ddkafka模組,但是如果在 segmentio目錄中加入了 go.mod,那麼 segmentio 就不再隸屬於 gitlab.luojilab.com/zeroteam/ddkafka模組。

那麼依賴被下載到哪裡了呢,你可以開啟的目錄 $GPATH/pkg/mod就可以看到了。

主模組和構建串列

The main module and the build list 暫且翻譯為主模組和構建串列。
“主模組” 是包含執行 go 命令的目錄的模組。 go 命令透過查詢當前目錄中的 go.mod 或者當前目錄的父目錄,或者祖父目錄,依次遞迴查詢。

go.mod 檔案可以透過 require,replace 和 exclude 陳述句使用的精確軟體包集。

  • require 陳述句指定的依賴項模組

  • replace 陳述句可以替換依賴項模組

  • exclude 陳述句可以忽略依賴項模組

go list,可以檢視當前的依賴和版本.

  1. qiang@DESKTOP-2A835P9 MINGW64 /d/code/gopath/src/gitlab.luojilab.com/zeroteam/ddkafka/segmentio (module)

  2. $ ls  # 這是模組的子目錄

  3. segmention_Consumer.go  segmention_consumer_test.go  segmention_producer.go  segmention_producter_test.go

  4. qiang@DESKTOP-2A835P9 MINGW64 /d/code/gopath/src/gitlab.luojilab.com/zeroteam/ddkafka/segmentio (module)

  5. $ go list -m #主模組的列印路徑

  6. gitlab.luojilab.com/zeroteam/ddkafka

  7. qiang@DESKTOP-2A835P9 MINGW64 /d/code/gopath/src/gitlab.luojilab.com/zeroteam/ddkafka/segmentio (module)

  8. $ go list -m -f={{.Dir}} #print主模組的根目錄

  9. D:\code\gopath\src\gitlab.luojilab.com\zeroteam\ddkafka

  10. qiang@DESKTOP-2A835P9 MINGW64 /d/code/gopath/src/gitlab.luojilab.com/zeroteam/ddkafka/segmentio (module)

  11. $ go list -m all # 檢視當前的依賴和版本資訊

  12. gitlab.luojilab.com/zeroteam/ddkafka

  13. github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b

  14. github.com/segmentio/kafka-go v0.0.0-20180716203113-48c37f796910

go mod 命令

go mod命令之前可以使用過了 go mod init,下麵我們把常用的 go mod命令羅列一下:

  • go mod init: 初始化 modules

  • go mod download: 下載 modules 到本地 cache

  • go mod edit: 編輯 go.mod 檔案,選項有 - json、-require 和 - exclude,可以使用幫助 go help mod edit

  • go mod graph: 以文字樣式列印模組需求圖

  • go mod tidy: 刪除錯誤或者不使用的 modules

  • go mod vendor: 生成 vendor 目錄

  • go mod verify: 驗證依賴是否正確

  • go mod why:查詢依賴

  1. qiang@DESKTOP-2A835P9 MINGW64 /d/code/gopath/src/gitlab.luojilab.com/zeroteam/ddkafka (module)

  2. $ go mod edit -json

  3. {

  4.        "Module": {

  5.                "Path": "gitlab.luojilab.com/zeroteam/ddkafka"

  6.        },

  7.        "Require": [

  8.                {

  9.                        "Path": "github.com/golang/glog",

  10.                        "Version": "v0.0.0-20160126235308-23def4e6c14b"

  11.                },

  12.                {

  13.                        "Path": "github.com/segmentio/kafka-go",

  14.                        "Version": "v0.0.0-20180716203113-48c37f796910"

  15.                }

  16.        ],

  17.        "Exclude": null,

  18.        "Replace": null

  19. }

  20. qiang@DESKTOP-2A835P9 MINGW64 /d/code/gopath/src/gitlab.luojilab.com/zeroteam/ddkafka (module)

  21. $ cat go.mod

  22. module gitlab.luojilab.com/zeroteam/ddkafka

  23. require (

  24.        github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b

  25.        github.com/segmentio/kafka-go v0.0.0-20180716203113-48c37f796910

  26. )

  27. qiang@DESKTOP-2A835P9 MINGW64 /d/code/gopath/src/gitlab.luojilab.com/zeroteam/ddkafka (module)

  28. $ go mod edit -require=github.com/Shopify/sarama@master

  29. qiang@DESKTOP-2A835P9 MINGW64 /d/code/gopath/src/gitlab.luojilab.com/zeroteam/ddkafka (module)

  30. $ cat go.mod

  31. module gitlab.luojilab.com/zeroteam/ddkafka

  32. require (

  33.        github.com/Shopify/sarama master

  34.        github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b

  35.        github.com/segmentio/kafka-go v0.0.0-20180716203113-48c37f796910

  36. )

  37. qiang@DESKTOP-2A835P9 MINGW64 /d/code/gopath/src/gitlab.luojilab.com/zeroteam/ddkafka (module)

  38. $ go mod vendor  # 啟動verdon

  39. go: downloading github.com/Shopify/sarama v1.17.1-0.20180820172058-647feef69a1a

  40. go: finding github.com/davecgh/go-spew/spew latest

  41. go: finding github.com/eapache/queue v1.1.0

  42. go: finding github.com/eapache/go-xerial-snappy latest

  43. go: finding github.com/eapache/go-resiliency/breaker latest

  44. go: finding github.com/rcrowley/go-metrics latest

  45. go: downloading github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165

  46. go: finding github.com/bsm/sarama-cluster v2.1.15+incompatible

  47. go: downloading github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21

  48. go: downloading github.com/bsm/sarama-cluster v2.1.15+incompatible

  49. go: downloading github.com/eapache/queue v1.1.0

  50. go: finding github.com/eapache/go-resiliency v1.1.0

  51. go: downloading github.com/eapache/go-resiliency v1.1.0

  52. go: finding github.com/davecgh/go-spew v1.1.1

  53. go: downloading github.com/davecgh/go-spew v1.1.1

  54. go: finding github.com/pierrec/lz4 v2.0.3+incompatible

  55. go: downloading github.com/pierrec/lz4 v2.0.3+incompatible

  56. go: finding github.com/golang/snappy latest

  57. go: downloading github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db

  58. qiang@DESKTOP-2A835P9 MINGW64 /d/code/gopath/src/gitlab.luojilab.com/zeroteam/ddkafka (module)

  59. $ ls

  60. README.md  go.mod  go.sum  models.go  mq_interface.go  sarama  segmentio  vendor

  61. qiang@DESKTOP-2A835P9 MINGW64 /d/code/gopath/src/gitlab.luojilab.com/zeroteam/ddkafka (module)

  62. $ go mod verify

  63. all modules verified

  64. qiang@DESKTOP-2A835P9 MINGW64 /d/code/gopath/src/gitlab.luojilab.com/zeroteam/ddkafka (module)

  65. $ go mod why

  66. go: finding github.com/onsi/ginkgo/extensions/table latest

  67. go: finding github.com/onsi/ginkgo v1.6.0

  68. go: finding github.com/Shopify/toxiproxy/client latest

  69. go: finding github.com/onsi/gomega v1.4.1

  70. go: downloading github.com/onsi/gomega v1.4.1

  71. go: downloading github.com/onsi/ginkgo v1.6.0

  72. go: finding github.com/onsi/ginkgo/extensions latest

  73. go: finding github.com/Shopify/toxiproxy v2.1.3+incompatible

  74. go: downloading github.com/Shopify/toxiproxy v2.1.3+incompatible

  75. go: finding github.com/hpcloud/tail v1.0.0

  76. go: finding github.com/golang/protobuf/proto latest

  77. go: finding gopkg.in/yaml.v2 v2.2.1

  78. go: downloading github.com/hpcloud/tail v1.0.0

  79. go: downloading gopkg.in/yaml.v2 v2.2.1

  80. go: finding github.com/golang/protobuf v1.2.0

  81. go: downloading github.com/golang/protobuf v1.2.0

  82. go: finding gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405

  83. go: downloading gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405

  84. go: finding gopkg.in/tomb.v1 latest

  85. go: finding gopkg.in/fsnotify.v1 v1.4.7

  86. go: downloading gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7

  87. go: downloading gopkg.in/fsnotify.v1 v1.4.7

  88. go: finding github.com/fsnotify/fsnotify v1.4.7

  89. go: downloading github.com/fsnotify/fsnotify v1.4.7

  90. # gitlab.luojilab.com/zeroteam/ddkafka

  91. gitlab.luojilab.com/zeroteam/ddkafka

go 的 mod 與 get

go get 這個命令大家應該不會陌生,這是下載 go 依賴包的根據,下載 Go 1.11 出來了,go get 命令也與時俱進,支援了 modules。
go get 來更新 module:

  • 執行 go get -u 將會升級到最新的次要版本或者修訂版本

  • 執行 go get -u=patch 將會升級到最新的修訂版本(比如說,將會升級到 1.0.1 版本,但不會升級到 1.1.0 版本)

  • 執行 go get package@version 將會升級到指定的版本號

執行 go get 如果有版本的更改,那麼 go.mod 檔案也會更改。

最後

最後說明一下最新出來的特性不建議立即使用到線上,最好再等等,等迭代一兩個版本之後,得帶最佳實踐出來之後,畢竟現在支援 modules 樣式的類庫還真不多。

附錄

  • https://tip.golang.org/cmd/go/#hdr-Modulesmoduleversionsandmore

  • https://roberto.selbach.ca/intro-to-go-modules

贊(0)

分享創造快樂

© 2024 知識星球   網站地圖