Golang Modules

魔幻涂鴉

前言


mod 是 modules 的簡稱,Go 1.11 和 Go 1.12 早已支持 modules。
在 Go 1.11 中 $GOPATH/src 目錄下,即使有 go.mod 那也是工作在 GOPATH 模式下;從 Go 1.13 開始默認為 module 模式。

modules 使用 semantic version tags 格式為:major.minor.patch(如:v0.1.2), major 為大版本號,minor 為小版本號,patch 為補丁號。

依賴包后面的 // indirect 注釋表明這個包是間接被這個 module 所依賴。

在 module 目錄下使用 go get xxx 會使 xxx 依賴包升至最新版本(默認為:go get xxx@latest),如果 xxx 是個間接依賴包被其它包所依賴時,并且這些包所需要的 xxx 版本為老版本并且新老版本不兼容的話,會使得編譯不通過。
可以使用 go get xxx@vmajor.minor.patch 獲取特定的依賴包。

module 允許同時依賴于某個包的不同主版本,但是特定主版本最多只能有一個。例如:可以同時依賴 xxx 的 v1 和 v2兩個版本,但不能同時依賴 v1 版本中的 v1.0.0 和 v1.0.1。
當(dāng)依賴多個主版本時使用 semantic import versioning 進行指定。例如:rsc.io/quote 表示 v1 版,rsc.io/quote/v2 表示 v2 版。

allowing different major versions of a module (because they have different paths) gives module consumers the ability to upgrade to a new major version incrementally

可以看出之所以可以這樣是因為不同的主版本的路徑必須是不同的,例如:rsc.io/quote 和 rsc.io/quote/v2 是兩個路徑。

這樣引入了一條規(guī)則:

If an old package and a new package have the same import path,
the new package must be backwards compatible with the old package.

所以對于 github/user/xxx 的開發(fā)者來說,當(dāng)他想開發(fā)第二個版本時,必須把 v2 版的代碼提交到 github/user/xxx/v2 路徑下(兩個路徑下都是完整的 module,分別有各自的 go.mod ),這樣使用者就可以有選擇的使用。
官方說使用版本后綴的方式管理包,是 go 有別于其他工具的地方,這樣可以解決菱形依賴問題。

$ pwd
/.../xxx
$ ls
README.md   one.go  two.go  ...
$ cat go.mod
module github.com/hengzi52125/xxx
go 1.13
require (
    ...
)
$
$
$ mkdir v2
$ cp *.go v2/
$ cp go.mod v2/go.mod
$ go mod edit -module github.com/hengzi52125/xxx/v2 v2/go.mod

依賴包會被下載到 $GOPATH/pkg/mod/ 目錄下,并帶有版本標記(例如:$GOPATH/pkg/mod/github.com/nfnt/resize@v0.0.0-20180221191011-83c6a9932646),當(dāng)下次另外的 module 用到同樣的包時不會重復(fù)下載。

對于未被 tag 的包(例如上面的 nfnt/resize 包,只有個 master 分支,而且沒有 Tag ),go 命令會自動生成個 preudo version 版本號, 如:v0.0.0-yyyymmddhhmmss-abcdef 時間為 commit UTC時間,abcdef 為 commit hash。

go.sum 文件列出依賴包的源碼的 SHA-256 哈希值,主要用于驗證從 GOPROXY 鏡像站點上下載下來的代碼有沒有被做篡改,保證安全。
所以 GOSUMDB 沒有鏡像站點,鑒于國內(nèi)網(wǎng)絡(luò)只能關(guān)閉該檢查功能,即 GOSUMDB="off"

使用 go mod init xxx 會自動創(chuàng)建 go.mod 文件,當(dāng)下載依賴后會自動創(chuàng)建 go.sum 文件。所以這兩個文件一般不需要手動創(chuàng)建。

GOPROXY 和 GOSUMDB


GOPROXY 協(xié)議流程:

proxy-protocol 來源于官方文檔

設(shè)置國內(nèi)鏡像站點 https://goproxy.cn :
go env -w GOPROXY="https://goproxy.cn,https://proxy.golang.org,direct"

GOSUMDB 協(xié)議流程:

sumdb-protocol 來源于官方文檔

關(guān)閉 GOSUMDB:
go env -w GOSUMDB="off"

go.mod 文件


module:指定本 module 的名字(路徑)

如果不是第一個主版本,如: v0 或 v1,則要在后面加上版本后綴

module github.com/hengzi52125/xxx/v2

require:指定依賴

多個依賴可以放在一個 "()" 里,就像 import 那樣

require (
    dependency1
    dependency2
)

replace:替換依賴

當(dāng)某些原因?qū)е?require 中的依賴下載不下來時,或者想導(dǎo)入本地的包時,可以使用 replace

replace (
    golang.org/x/image vx.y.z => github.com/golang/image vx.y.z
    a-package vx.y.z => /Users/...
)

exclude:排除依賴

舉個栗子:假設(shè)在代碼中 import github.com/user/xxx, 對于這個 xxx 它現(xiàn)在最新的版本是 v1.1.1 , 但是你不想用 v1.1.1, 于是就可以把它放入 exclude 中

exclude github.com/user/xxx v1.1.1

使用


創(chuàng)建 module
go mod init github.com/hengzi52125/xxx

導(dǎo)入依賴
正常編寫代碼,當(dāng)執(zhí)行 go test/run/build 等命令時會自動導(dǎo)入最新的依賴包(“Latest” is defined as the latest tagged stable (non-prerelease) version, or else the latest tagged prerelease version, or else the latest untagged version.)

go get foo@v1.2.3 可以導(dǎo)入特定版本的依賴,@ 后面可以跟 git 的 branch、tag、commit hash。如果使用的是分支,如:go get foo@master 那么只會下載一次,即下次執(zhí)行 go get foo@master 時不會再去下載,直接用本地的,即使 master 上代碼有更新。

go mod download : 下載依賴包

查看依賴
go list -m all :會列出當(dāng)前的 module 和它所有的依賴(包括間接依賴)

go list -m -versions xxx :列出 xxx 的所有版本

go doc xxx/v3 :查看文檔

go mod graph :打印模塊依賴圖

清除無用的依賴
go mod tidy :清除未被使用的依賴,或?qū)胨枰蕾嚕▽?dǎo)入最新的版本)

升降級依賴
go list -u -m all :升級并查看所有依賴(go list -u 只能搭配 -m 才能使用)

go get -u xxx :升級 minor 或 patch 版本號

go get -u=patch xxx :只升級 patch 版本號

go get xxx@'<vx.y.z' : 使用大于小于等比較運算符進行升降級

格式化 go.mod
go mod edit -fmt :如果手動修改了 go.mod 變得格式不美觀了,可以用其格式化

參考鏈接


preudo-version
Go Modules: v2 and Beyond
Publishing Go Modules
Module Mirror and Checksum Database Launched
Using Go Modules

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容