今天要來筆記一下學到的 Go Module 的指令,這篇文章只會紀錄一些我覺得會常用的指令,並不會說明什麼是 Module,如果要了解什麼是 Module 可以參考 Go 1.11 Modules

此文章會說明的指令有 $ go mod init <module name>, $ go list, $ go get, $ go mod verify, $ go mod tidy, $ go mod why <package>, $ go mod edit, $ go mod vendor

初始化 Module

初始化 Module 的指令: $ go mod init <module name>

init 範例
  • bash
1
$ go mod init github.com/mileslin/myproject

上述範例 module name github.com/mileslin/myproject 的意義

  • 在 build go 專案的時候,會根據 module name 的最後一路路徑 myproject 當作輸出檔名,會產生 myproject.exe 的檔案
  • 在 import 自己專案 package 的路徑的時候,github.com/mileslin/myproject 是根目錄,例如我新增一個 pg1 的 package ,則我在 import 的時候要輸入 import "github.com/mileslin/myproject/pg1"

在初始化完畢後,會產生一個 go.mod 檔案,這是用來紀錄相依套件的檔案。 go.mod 檔案的範例如下

mod
  • mod
1
2
3
module github.com/mileslin/myproject

go 1.13

取得套件

跟原本的 go get 取得套件的方式一樣,如: $ go get -u github.com/gorilla/mux (-u 是說明,取得套件的時候不要從 cache 取得)。 取得套件後會產生一個 的檔案,這個檔案裡面有套件的 hash ,用來驗證你下載的套件沒有被經過串改。

除了會新增一個 go.sum 檔案之外呢, go.mod 也會記錄你下載的套件,如下範例

go.mod
  • mod
1
2
3
4
5
module github.com/mileslin/myproject

go 1.13

require github.com/gorilla/mux v1.7.3 // indirect

// indirect 的意思是說,此套件還沒被用到。 所以只要在程式碼中使用此到件,並且 build 專案後,// indirect 就會消失

最後提一下,下載的套件會被放在 GOPATH/pkg/mod 底下。 (可以使用 go env 指令查看 GOPATH 路徑)

列出套件與套件版本

使用 $ go list 取得可以使用的套件列表,常用方式如下

  • $ go list all 會列出所有套件,包含 GOROOT 套件
  • $ go list -m all 只列出 module 列出的套件(包含自己的 package)
  • $ go list -m -versions github.com/gorilla/mux 列出此套件的所有版本

驗證套件的正確性

使用 $ go mod verify 可以驗證套件在下載之後,有沒有在本機上被修改過。 而驗證方式是根據套件 source code 產生的 hash,來做比對,此 hash 是存在 go.sum 裡面。

注意: $ go build . 的時候並不會驗證。 只有執行 $ go mod verify 指令才驗證套件是否被串改。

補充: 如果不小心改了套件 source code ,只要把套件從 GOPATH/pkg/mod 底下刪除,重新 $ go get 該套件,就可以恢復正常。

清除用不到的套件

有些套件已經記錄在 go.mod 裡面,但是實際上此套件在專案裡面沒有用到,則可以使用 $ go mod tidy 指令,來清楚用不到的專案。 執行此指令後,就會 go.mod 裡面沒用到的套件拿掉。

取得不同版本的套件

$ go get 如果沒有特別指定版本的話,預設會抓穩定版第 1 版的套件。 如果要抓其他版本的話,可以先用 $ go list -m -versions github.com/gorilla/mux 指令來查詢有哪些版本可以用,然後在 $ go get 的時候指定版本,如 $ go get github.com/gorilla/mux@v1.6.1

Go Module 套件的版本說明: Semantic Import Versioning

檢查套件使用情形

使用 $ go mod why github.com/gorilla/mux 他會就列出使套件在哪裡有被用到,這算是在檢查套件的時候,蠻實用的一個指令。

用指令編輯 go.mod

$ go mod edit 是一種可以使用指令的方式來修改 go.mod 檔案,使用情境通常是在整合 CI/CD 的時候使用。 其他一般情況,其實只要手動修改 go.mod 檔案就可以了,不需要用到 $ go mod edit 指令。

$ go mod edit 一些簡單的用法如下

  • $ go mod edit -print, $ go mod edit -json 印出 go.mod 檔案
  • $ go mod edit -require github.com/gorilla/context@v1.1.1 requrie 其他套件

參考: Edit go.mod from tools or scripts

使用 vendor directory

Vendor Directories 是在 Go Module 還沒有出來之前,一種管理套件的方式。 既然我們現在有 Go Module 的方式管理套件了,這方式還是不太建議。

但是此方式還是有它的使用情境,例如 IT 部門在 Production 環境不許允連網路,這樣就沒辦法使用 $ go get 來下載套件,這時候我們可以使用 vendor directory 的方式,把套件的檔案都準備好,這樣就不用額外在 $ go get 檔案

啟用 vendor directory 的指令 $ go mod vendor,執行完畢後,就會看到專案裡面多一個 vendor 的資料夾,該資料夾就是存放第三方套件的地方。

啟用 vendor directory 後,建置專案的方式

如果執行 $ go run .$ go build . 的時候會發現,實際上程式也是會去抓 GOPATH/pkg/mod 的套件,而不是專案底下的 vendor 套件。

如果要使用專案底下 vendor 的檔案來 build 專案的話,必須加入一些參數,使用方法如 $ go run -mod=vendor ., $ go build -mod=vendor .

小結

今天的筆記都是從 Exploring Go Modules by pluralsight 這個課程來的,如果有 pluralsight 的訂閱讀者,很推薦此課程。

延伸閱讀

[Go 1.11 Modules]
[Semantic Versioning]
[Exploring Go Modules - pluralsight]
[Go Command]