【Golang】go mod 使用

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(解釋爲什麼需要依賴)
如何在項目中使用
  1. 在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 語句可以忽略依賴項模塊
  2. 新建一個 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=
    ... 省略很多行
    
  3. 再次執行腳本 go run server.go 發現跳過了檢查並安裝依賴的步驟。

  4. 可以使用命令 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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章