go modules 是 golang 1.11 新加的特性。現在1.12 已經發布了,是時候用起來了。Modules官方定義爲:
模塊是相關Go包的集合。modules是源代碼交換和版本控制的單元。 go命令直接支持使用modules,包括記錄和解析對其他模塊的依賴性。modules替換舊的基於GOPATH的方法來指定在給定構建中使用哪些源文件。
如何使用 Modules ?
- 把 golang 升級到 1.11(現在1.12 已經發布了,建議使用1.12)
- 設置 GO111MODULE
GO111MODULE
GO111MODULE 有三個值:off, on和auto(默認值)。
- GO111MODULE=off,go命令行將不會支持module功能,尋找依賴包的方式將會沿用舊版本那種通過vendor目錄或者GOPATH模式來查找。
- GO111MODULE=on,go命令行會使用modules,而一點也不會去GOPATH目錄下查找。
- GO111MODULE=auto,默認值,go命令行將會根據當前目錄來決定是否啓用module功能。這種情況下可以分爲兩種情形:
- 當前目錄在GOPATH/src之外且該目錄包含go.mod文件
- 當前文件在包含go.mod文件的目錄下面。
當modules 功能啓用時,依賴包的存放位置變更爲$GOPATH/pkg,允許同一個package多個版本並存,且多個項目可以共享緩存的 module。
go mod
golang 提供了 go mod命令來管理包。
go mod 有以下命令:
命令 | 說明 |
---|---|
download | download modules to local cache(下載依賴包) |
edit | edit go.mod from tools or scripts(編輯go.mod) |
graph | print module requirement graph (打印模塊依賴圖) |
init | initialize new module in current directory(在當前目錄初始化mod) |
tidy | add missing and remove unused modules(拉取缺少的模塊,移除不用的模塊) |
vendor | make vendored copy of dependencies(將依賴複製到vendor下) |
verify | verify dependencies have expected content (驗證依賴是否正確) |
why | explain why packages or modules are needed(解釋爲什麼需要依賴) |
如何在項目中使用
-
在GOPATH 目錄之外新建一個目錄,並使用go mod init 初始化生成go.mod 文件:
➜ ~ mkdir hello ➜ ~ cd hello ➜ hello go mod init hello go: creating new go.mod: module hello ➜ hello ls go.mod ➜ hello cat go.mod module hello go 1.12
go.mod文件一旦創建後,它的內容將會被go toolchain全面掌控。go toolchain會在各類命令執行時,比如go get、go build、go mod等修改和維護go.mod文件。
go.mod 提供了module, require、replace和exclude 四個命令
- module 語句指定包的名字(路徑)
- require 語句指定的依賴項模塊
- replace 語句可以替換依賴項模塊
- exclude 語句可以忽略依賴項模塊
-
新建一個 server.go 文件,寫入以下代碼:
package main import ( "net/http" "github.com/labstack/echo" ) func main() { e := echo.New() e.GET("/", func(c echo.Context) error { return c.String(http.StatusOK, "Hello, World!") }) e.Logger.Fatal(e.Start(":1323")) }
執行 go run server.go 運行代碼會發現 go mod 會自動查找依賴自動下載:
$ go run server.go go: finding github.com/labstack/echo v3.3.10+incompatible go: downloading github.com/labstack/echo v3.3.10+incompatible go: extracting github.com/labstack/echo v3.3.10+incompatible go: finding github.com/labstack/gommon/color latest go: finding github.com/labstack/gommon/log latest go: finding github.com/labstack/gommon v0.2.8 # 此處省略很多行 ... ____ __ / __/___/ / ___ / _// __/ _ \/ _ \ /___/\__/_//_/\___/ v3.3.10-dev High performance, minimalist Go web framework https://echo.labstack.com ____________________________________O/_______ O\ ⇨ http server started on [::]:1323
現在查看go.mod 內容:
$ cat go.mod module hello go 1.12 require ( github.com/labstack/echo v3.3.10+incompatible // indirect github.com/labstack/gommon v0.2.8 // indirect github.com/mattn/go-colorable v0.1.1 // indirect github.com/mattn/go-isatty v0.0.7 // indirect github.com/valyala/fasttemplate v1.0.0 // indirect golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a // indirect )
go module 安裝 package 的原則是先拉最新的 release tag,若無tag則拉最新的commit,詳見 Modules官方介紹。 go 會自動生成一個 go.sum 文件來記錄 dependency tree:
$ cat go.sum github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg= github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s= github.com/labstack/gommon v0.2.8 h1:JvRqmeZcfrHC5u6uVleB4NxxNbzx6gpbJiQknDbKQu0= github.com/labstack/gommon v0.2.8/go.mod h1:/tj9csK2iPSBvn+3NLM9e52usepMtrd5ilFYA+wQNJ4= github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= ... 省略很多行
-
再次執行腳本 go run server.go 發現跳過了檢查並安裝依賴的步驟。
-
可以使用命令 go list -m -u all 來檢查可以升級的package,使用go get -u need-upgrade-package 升級後會將新的依賴版本更新到go.mod * 也可以使用 go get -u 升級所有依賴
go get 升級
- 運行 go get -u 將會升級到最新的次要版本或者修訂版本(x.y.z, z是修訂版本號, y是次要版本號)
- 運行 go get -u=patch 將會升級到最新的修訂版本
- 運行 go get package@version 將會升級到指定的版本號version
- 運行go get如果有版本的更改,那麼go.mod文件也會更改
使用replace替換無法直接獲取的package
由於某些已知的原因,並不是所有的package都能成功下載,比如:golang.org下的包。
modules 可以通過在 go.mod 文件中使用 replace 指令替換成github上對應的庫,比如:
replace (
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a => github.com/golang/crypto v0.0.0-20190313024323-a1f597ede03a
)
或者
replace golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a => github.com/golang/crypto v0.0.0-20190313024323-a1f597ede03a