Go Modules基礎

1. 簡介

GO Modules 也稱作 go mod 是golang 官方最新的幾個golang 版本中推出的 管理方式或者稱作模塊支持

golang 中 modules (模塊)是什麼意思呢?

一個模塊是一系列 Go 代碼包 的集合,它們保存在同一個文件樹中。文件樹的根目錄中包含了一個 go.mod 文件。go.mod 文件定義了一個模塊的 module path,這就是模塊根目錄的導入路徑。go.mod 文件還定義了模塊的 dependency requirements(依賴項要求),即爲了編譯本模塊,需要用到哪些其它的模塊。每一項依賴項要求都包含了依賴項的 module path,還要指定它的語義版本號

在最新的golang版本golang 1.13中是默認的包管理方式,那麼在golang的後期版本中 Go Modules 基本可以認爲是官方推薦的依賴管理工具

GO modules 是解決啥問題的?

Golang在早期的版本中(golang 1.11版本之前) 包管理一直沒有一個統一方案,表現出問題如:

  1. 所有的依賴包都必須在GOPATH同一個庫只能保存一個版本的代碼,那麼不同的項目要依賴同一個包的不同版本那就很尷尬了.
  2. 工作目錄必須在 GOPATH/src 目錄下

使用了Go Modules 之後就可在GOPATh/src 之外創建目錄和管理包了

我們大概回顧一下

  1. golang 1.5 版本之前所有的依賴包都必須放在 GOPATH 下面,沒有版本管理
  2. golang 1.5 版本之後推出 vendor 機制
  3. golang 1.9 版本出現了包管理工具 dep
  4. golang1.11 版本推出 modules 機制對包進行管理,在之後的版本中modules 逐步得到了加強, 在golang1.13 中成爲默認的包管理方式並且是默認開啓的

2. 基礎命令

go mod 的命令其實不多

我們打開命令行工具

$ go help mod
Go mod provides access to operations on modules.

Note that support for modules is built into all the go commands,
not just 'go mod'. For example, day-to-day adding, removing, upgrading,
and downgrading of dependencies should be done using 'go get'.
See 'go help modules' for an overview of module functionality.

Usage:

        go mod <command> [arguments]

The commands are:

        download    download modules to local cache
        edit        edit go.mod from tools or scripts
        graph       print module requirement graph
        init        initialize new module in current directory
        tidy        add missing and remove unused modules
        vendor      make vendored copy of dependencies
        verify      verify dependencies have expected content
        why         explain why packages or modules are needed

Use "go help mod <command>" for more information about a command.

顯示的 go mod 實際命令只有如下幾個

命令 意思
go mod download 下載依賴的Module到本地緩存
go mod edit 編輯go.mod文件
go mod graph 打印模塊依賴圖
go mod init 初始化當前目錄中的新模塊,創建go.mod文件
go mod tidy 增加缺失的Module,刪除無效的Module
go mod vendor 將依賴複製到vendor下
go mod verify 校驗依賴
go mod why 解釋package或者modules爲啥被依賴

3. 基本使用

3.1 go mod init

我們在非GOPATH/src 目錄下執行

go mod init 後面是模塊名稱 ,名稱自定義即可

$ go mod init github.com/captain/modDemo
go: creating new go.mod: module github.com/captain/modDemo

這樣在項目(模塊)目錄下多出了一個文件go.mod 文件

我們看看go.mod 中的內容

module github.com/captain/modDemo

go 1.12

我們下載一個依賴包試試

// 執行 如下命令
go get -u github.com/gin-gonic/gin

初次執行下依賴包的命令後會多出一個文件 go.sum

go.sum 是由 go命令行工具維護的,其中記錄了每個依賴庫的版本和哈希值,其作用是確保項目依賴的模塊不會發生變化

執行完之後,我們再看看go.mod 的內容

module github.com/apiDemo

go 1.12

require (
	github.com/gin-gonic/gin v1.5.0 // indirect
	github.com/go-playground/universal-translator v0.17.0 // indirect
	github.com/json-iterator/go v1.1.8 // indirect
	github.com/leodido/go-urn v1.2.0 // indirect
	github.com/mattn/go-isatty v0.0.10 // indirect
	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
	github.com/modern-go/reflect2 v1.0.1 // indirect
	github.com/stretchr/objx v0.2.0 // indirect
	golang.org/x/crypto v0.0.0-20191128160524-b544559bb6d1 // indirect
	golang.org/x/net v0.0.0-20191126235420-ef20fe5d7933 // indirect
	golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect
	golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9 // indirect
	golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d // indirect
	golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 // indirect
	gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
	gopkg.in/go-playground/validator.v9 v9.30.2 // indirect
	gopkg.in/yaml.v2 v2.2.7 // indirect
)

go.mod 文件簡介:

module 用來定義包名和我們初始化的包名是一致的

require 定義依賴的包及其對應的版本

indirect 標識間接引用

3.1 下載指定版本的依賴庫

go list -m all 列出當前模塊和它的依賴庫

$ go list -m all
github.com/captain/modDemo
github.com/davecgh/go-spew v1.1.1
github.com/gin-contrib/sse v0.1.0
github.com/gin-gonic/gin v1.5.0
github.com/go-playground/locales v0.13.0
github.com/go-playground/universal-translator v0.17.0
github.com/golang/protobuf v1.3.2
github.com/google/gofuzz v1.0.0
github.com/json-iterator/go v1.1.8
github.com/leodido/go-urn v1.2.0
github.com/mattn/go-isatty v0.0.10
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
github.com/modern-go/reflect2 v1.0.1
github.com/pmezard/go-difflib v1.0.0
github.com/stretchr/objx v0.2.0
github.com/stretchr/testify v1.4.0
github.com/ugorji/go v1.1.7
github.com/ugorji/go/codec v1.1.7
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413
golang.org/x/net v0.0.0-20191207000613-e7e4b65ae663
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
golang.org/x/sys v0.0.0-20191206220618-eeba5f6aabab
golang.org/x/text v0.3.2
golang.org/x/tools v0.0.0-20191206204035-259af5ff87bd
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15
gopkg.in/go-playground/assert.v1 v1.2.1
gopkg.in/go-playground/validator.v9 v9.30.2
gopkg.in/yaml.v2 v2.2.7

go list -m -versions 庫名地址 列出一個模塊能用的版本

$ go list -m -versions github.com/gin-gonic/gin
github.com/gin-gonic/gin v1.1.1 v1.1.2 v1.1.3 v1.1.4 v1.3.0 v1.4.0 v1.5.0

go mod tidy 刪除無效的modules

$ go mod tidy
$ go list -m all
github.com/captain/modDemo

我們拿比較常見的 一個庫xrom做示例 下載指定的版本

可見 xorm可用的版本很多

$ go list -m -versions github.com/go-xorm/xorm
github.com/go-xorm/xorm v0.2.1 v0.2.2 v0.2.3 v0.3.1 v0.3.2 v0.4.1 v0.4.2 v0.4.3 v0.4.4 v0.4.5 v0.5.0 v0.5.1 v0.5.2 v0.5.3 v0.5.4 v0.5.6 v0.5.7 v0.5.8 v0.6.2 v0.6.3 v0.6.4 v0.6.5 v0.6.6 v0.7.0 v0.7.1 v0.7.2 v0.7.3 v0.7.4 v0.7.5 v0.7.6 v0.7.7 v0.7.8 v0.7.9

go mod 想下載指定的版本 通常我們有三種做法

  1. go get 包路徑@v版本號
  2. go get 包路徑@分支 分支是指在github上提交的分支
  3. go get 包路徑@git提交的哈希

我們看到目前 xorm 最新版本是 v0.7.9 但是我想下載比較舊一點的版本 v0.7.5

$ go get github.com/go-xorm/[email protected]
go: finding github.com/go-xorm/xorm v0.7.5
go: finding github.com/jackc/pgx v3.3.0+incompatible
go: finding xorm.io/core v0.7.0
go: finding github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4
go: finding github.com/cockroachdb/apd v1.1.0
go: finding xorm.io/builder v0.3.5
go: finding github.com/jackc/fake v0.0.0-20150926172116-812a484cc733
go: finding github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24
go: finding github.com/ziutek/mymysql v1.5.4
go: finding github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a
go: finding golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468
go: finding google.golang.org/appengine v1.6.0
go: finding golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed
go: downloading github.com/go-xorm/xorm v0.7.5
go: extracting github.com/go-xorm/xorm v0.7.5
go: downloading xorm.io/builder v0.3.5
go: downloading xorm.io/core v0.7.0
go: extracting xorm.io/builder v0.3.5
go: extracting xorm.io/core v0.7.0

$ cat go.mod
module github.com/captain/modDemo

go 1.12

require github.com/go-xorm/xorm v0.7.5 // indirect

3.2 更新依賴庫

通常下載一個包沒有明確指定版本,那麼下載的包就是當前的最新版本

我們還是拿 xorm 包作爲示例

$ go get github.com/go-xorm/xorm
go: finding github.com/jackc/pgx v3.6.0+incompatible
go: finding xorm.io/builder v0.3.6
go: finding xorm.io/core v0.7.2-0.20190928055935-90aeac8d08eb
go: downloading github.com/go-xorm/xorm v0.7.9
go: extracting github.com/go-xorm/xorm v0.7.9
go: downloading xorm.io/core v0.7.2-0.20190928055935-90aeac8d08eb
go: downloading xorm.io/builder v0.3.6
go: extracting xorm.io/core v0.7.2-0.20190928055935-90aeac8d08eb
go: extracting xorm.io/builder v0.3.6
$ cat go.mod
module github.com/captain/modDemo

go 1.12

require (
        github.com/go-xorm/xorm v0.7.9 // indirect
        github.com/golang/protobuf v1.3.1 // indirect
        github.com/kr/pretty v0.1.0 // indirect
        github.com/satori/go.uuid v1.2.0 // indirect
        golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 // indirect
        golang.org/x/net v0.0.0-20190603091049-60506f45cf65 // indirect
        golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed // indirect
        golang.org/x/text v0.3.2 // indirect
        golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468 // indirect
)

我們看到了結果現在xorm 更新到了當前最新版本v0.7.9

那我可不可以更新到一個指定的版本呢?其實做法是一樣的就是指定一個版本號就可以了

$ go get github.com/go-xorm/[email protected]
go: finding github.com/go-xorm/xorm v0.7.7
go: finding xorm.io/builder v0.3.6-0.20190906062455-b937eb46ecfb
go: downloading github.com/go-xorm/xorm v0.7.7
go: extracting github.com/go-xorm/xorm v0.7.7

$ cat go.mod
module github.com/captain/modDemo

go 1.12

require (
        github.com/go-xorm/xorm v0.7.7 // indirect
        github.com/golang/protobuf v1.3.1 // indirect
        github.com/kr/pretty v0.1.0 // indirect
        github.com/satori/go.uuid v1.2.0 // indirect
        golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 // indirect
        golang.org/x/net v0.0.0-20190603091049-60506f45cf65 // indirect
        golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed // indirect
        golang.org/x/text v0.3.2 // indirect
        golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468 // indirect
        xorm.io/builder v0.3.6 // indirect
        xorm.io/core v0.7.2-0.20190928055935-90aeac8d08eb // indirect
)

3.3 go get簡介

go get 命令可以遠程拉取更新代碼包和依賴包,並自動完成編譯和安裝

go get 命令實際是分成了兩步操作 1. 下載源碼包 2.執行 go insert

簡單的理解是 :

go get = git clone + go insert

這是一個常見的遠程包的格式 : github.com/go-xorm/xorm

github.com 是網站域名

go-xorm 我們可以理解問作者或者機構名稱

xorm 就是項目名稱

go get 命令的具體詳情可以查看它的幫助命令

對命令附帶的可用參數有很詳細的介紹

$ go help get
usage: go get [-d] [-m] [-u] [-v] [-insecure] [build flags] [packages]

Get resolves and adds dependencies to the current development module
and then builds and installs them.

The first step is to resolve which dependencies to add.

我們只看幾個很常見的

-d 只下載,而不安裝

-u 強制使用網絡去更新包和它的依賴包

-v 顯示執行的命令

-t 同時也下載需要爲運行測試所需要的包

-fix 讓命令程序在下載代碼包後先執行修正動作,而後再進行編譯和安裝。

-x 打印安裝的具體過程

-insecure 允許命令程序使用非安全的scheme(如HTTP)去下載指定的代碼包

-f 僅在使用-u標記時纔有效。該標記會讓命令程序忽略掉對已下載代碼包的導入路徑的檢查

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章