一文讓你完全弄懂Go Modules模式媳纬!

Go Modules 模式

GOPATH 目錄

GOPATH 目錄下一共包含三個(gè)子目錄:

  • bin:存儲(chǔ)所編譯生成的二進(jìn)制文件倦卖。
  • pkg:存儲(chǔ)預(yù)編譯的目標(biāo)文件释簿,以加快程序的后續(xù)編譯速度钦听。
  • src:存儲(chǔ)所有 .go 文件或源代碼。在編寫 Go 應(yīng)用程序倍奢,程序包和庫(kù)時(shí)朴上,一般會(huì)以 $GOPATH/src/github.com/foo/bar 的路徑進(jìn)行存放。

使用 go get 來(lái)拉取外部依賴時(shí)卒煞,會(huì)自動(dòng)下載并安裝到 $GOPATH 目錄下痪宰。

go mod 命令

查看 go mod 都有哪些命令

# Go 的所有工具都可以使用 `go help` 來(lái)查看使用方法
go help mod

# 查看 go mod download 有哪些參數(shù)
go help mod download
命令 作用
go mod help 查看幫助信息
go mod init 初始化當(dāng)前文件夾,生成 go.mod 文件
go mod download 下載 go.mod 文件中指明的所有依賴到本地(默認(rèn)為 $GOPATH/pkg/mod 目錄)增加 -x 參數(shù) go mod download -x 會(huì)打印下載信息畔裕;go mod download -json 用來(lái)查看模塊下載的 zip 存放位置衣撬,以及解壓后的位置;
go mod tidy 整理現(xiàn)有的依賴扮饶,執(zhí)行時(shí)會(huì)把未使用的 module 移除掉具练,同時(shí)也會(huì)增加缺少的包
go mod graph 查看現(xiàn)有的依賴結(jié)構(gòu)圖
go mod edit 編輯 go.mod 文件,比如修改項(xiàng)目中使用的 go 版本 go mod edit -go=1.17
go mod vendor 導(dǎo)出項(xiàng)目所有的依賴到 vendor 目錄(需要執(zhí)行 go build -mod=vendor 才可以使用 vendor 作為依賴來(lái)編譯甜无,但是在 v1.14 及以后的版本中扛点,如果 golang 項(xiàng)目根目錄下存在 vendor 目錄,go build 命令會(huì)默認(rèn)優(yōu)先基于 vendor 目錄緩存的三方依賴包構(gòu)建 golang 程序岂丘,除非我們?cè)?go build 命令后面加上 -mod=mod 參數(shù))
go mod verify 校驗(yàn)一個(gè)模塊是否被篡改過(guò)陵究,校驗(yàn)從 GOPROXY 服務(wù)器上下載的 zip 文件與 GOSUMDB 服務(wù)器下載下來(lái)的哈希值,是否匹配奥帘。
go mod why 查看為什么需要依賴某模塊铜邮,比如 go mod why gopkg.in/yaml.v2 gopkg.in/yaml.v3
go clean -modcache 可以清空本地下載的 Go Modules 緩存 (會(huì)清空 $GOPATH/pkg/mod 目錄)

go mod 環(huán)境變量

go mod 比較關(guān)聯(lián)的幾個(gè)環(huán)境變量


go env

GO111MODULE="auto"
GOPROXY="https://goproxy.cn,direct"
GOSUMDB="sum.golang.org"
GONOPROXY=""
GONOSUMDB=""
GOPRIVATE=""

GO111MODULE

Go 語(yǔ)言提供了 GO111MODULE 這個(gè)環(huán)境變量來(lái)作為 Go modules 的開關(guān),其允許設(shè)置以下參數(shù):

  • auto:只要項(xiàng)目包含了 go.mod 文件的話啟用 Go modules,目前在 Go1.11 至 Go 1.14 中仍然是默認(rèn)值
  • on:?jiǎn)⒂?Go modules松蒜,推薦設(shè)置扔茅,將會(huì)是未來(lái)版本中的默認(rèn)值
  • off:禁用 Go modules,不推薦設(shè)置

設(shè)置方式

go env -w GO111MODULE=on

也可以直接在 shell 環(huán)境變量中設(shè)置牍鞠,比如我這里使用的是 Mac咖摹,且使用的 zsh,則在 vim ~/.zshrc 然后添加以下內(nèi)容难述,如果是其它 Linux 系列系統(tǒng)萤晴,則需要在 ~/.bash_profile 文件中進(jìn)行設(shè)置。


export GO111MODULE=on

然后要記得 source ~/.zshrc

GOPROXY

這個(gè)環(huán)境變量主要是用于設(shè)置 Go 模塊代理(Go module proxy)胁后,其作用是用于使 Go 在后續(xù)拉取模塊版本時(shí)直接通過(guò)鏡像站點(diǎn)來(lái)快速拉取

GOPROXY 的默認(rèn)值是:https://proxy.golang.org,direct


# 1. 七牛 CDN
go env -w  GOPROXY=https://goproxy.cn,direct

# 2. 阿里云
go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/,direct

# 3. 官方
go env -w  GOPROXY=https://goproxy.io,direct

direct 是一個(gè)特殊指示符店读,用于指示 Go 在獲取源碼包時(shí),先嘗試在設(shè)置 GOPROXY 的地址下抓取攀芯,如果遇到 404 或 410 等錯(cuò)誤時(shí)屯断,再回溯到模塊版本的源地址去抓取 (比如 GitHub 等)。

GOSUMDB

它的值是一個(gè) Go checksum database侣诺,用于在拉取模塊版本時(shí)(無(wú)論是從源站拉取還是通過(guò) Go module proxy 拉戎逞荨)保證拉取到的模塊版本數(shù)據(jù)未經(jīng)過(guò)篡改,若發(fā)現(xiàn)不一致年鸳,也就是可能存在篡改趴久,將會(huì)立即終止。

GOSUMDB 的默認(rèn)值為:sum.golang.org搔确,在國(guó)內(nèi)也是無(wú)法訪問(wèn)的彼棍,但是 GOSUMDB 可以被 Go 模塊代理所代理,因此我們可以通過(guò)設(shè)置 GOPROXY 來(lái)解決膳算,而先前我們所設(shè)置的模塊代理 goproxy.cn (七牛云的 CDN)就能支持代理 sum.golang.org座硕,所以這一個(gè)問(wèn)題在設(shè)置 GOPROXY 后,可以不需要過(guò)度關(guān)心涕蜂。

也可以將其設(shè)置為 off 华匾,也就是禁止 Go 在后續(xù)操作中校驗(yàn)?zāi)K版本。但是不建議關(guān)閉校驗(yàn)机隙。

GONOPROXY/GONOSUMDB/GOPRIVATE

  • GONOPROXY —— 設(shè)置不走 Go Proxy 的 URL 規(guī)則瘦真;
  • GONOSUMDB —— 設(shè)置不檢查哈希的 URL 規(guī)則;
  • GOPRIVATE —— 設(shè)置私有模塊的 URL 規(guī)則黍瞧,會(huì)同時(shí)設(shè)置以上兩個(gè)變量诸尽。

這三個(gè)環(huán)境變量都是用在當(dāng)前項(xiàng)目依賴了私有模塊,例如自己公司部署的私有 git 倉(cāng)庫(kù)或者是 GitHub 中的私有倉(cāng)庫(kù)印颤,都是需要進(jìn)行設(shè)置的您机,否則會(huì)拉取失敗。

設(shè)置 GOPRIVATE 之后,表示該地址為私有倉(cāng)庫(kù)际看,不會(huì)從 GOPROXY 所對(duì)應(yīng)的地址上去下載咸产。

而一般建議直接設(shè)置 GOPRIVATE,它的值將作為 GONOPROXY 和 GONOSUMDB 的默認(rèn)值仲闽,所以建議直接設(shè)置 GOPRIVATE 即可脑溢。


# 以下表示 git.example.com 和 github.com/username/package 都是私有倉(cāng)庫(kù),不會(huì)進(jìn)行 GOPROXY 下載和校驗(yàn)
go env -w GOPRIVATE="git.example.com,github.com/username/package"
# 設(shè)置后赖欣,前綴為 `git.example.com` 和 `github.com/username/package` 的模塊都會(huì)被認(rèn)為是私有模塊

# 表示所有模塊路徑為 example.com 的子域名都不進(jìn)行 GOPROXY 下載和校驗(yàn)
# 需要注意的是不包括 example.com 本身
go env -w GOPRIVATE="*.example.com"

使用 Go Modules 初始化項(xiàng)目


# 開啟 Go Modules 模塊屑彻,保證 GO111MODULE=on
go env -w GO111MODULE=on

# 在任意文件夾下創(chuàng)建一個(gè)項(xiàng)目(不要求在 $GOPATH/src 目錄下創(chuàng)建)
mkdir -p $HOME/modules_test

cd $HOME/modules_test

# 創(chuàng)建 go.mod 文件,同時(shí)起當(dāng)前項(xiàng)目的模塊名稱
# 如果你是在 `$GOPATH/src` 目錄下創(chuàng)建的文件夾可以直接執(zhí)行 `go mod init` 命令初始化顶吮,不需要加模塊名稱
go mod init github.com/pudongping/moudles_test

# 在該項(xiàng)目下編寫源代碼社牲,并下載依賴庫(kù)
# 也可以不加 `-v` 參數(shù)
go get -v XXXXXXXX

eg: go get -v github.com/pudongping/test_moudles

下載的包其實(shí)被緩存在 $GOPATH/pkg/mod 目錄和 $GOPATH/pkg/sumdb 目錄下

  • go.mod 文件中:
  1. module:用于定義當(dāng)前項(xiàng)目的模塊路徑。
  2. go:用于標(biāo)識(shí)當(dāng)前模塊的 Go 語(yǔ)言版本悴了,值為初始化模塊時(shí)的版本搏恤。
  3. require:用于設(shè)置一個(gè)特定的模塊版本。
  4. exclude:用于從使用中排除一個(gè)特定的模塊版本湃交。
  5. replace:用于將一個(gè)模塊版本替換為另外一個(gè)模塊版本熟空。
# v0.0.0 表示版本信息
# 20190718012654 表示所拉取版本的 commit 時(shí)間
# fb15b899a751 表示所拉取版本的 commit 哈希值
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
  • go.sum 文件中:

go.sum 文件的作用是:羅列當(dāng)前項(xiàng)目直接或間接依賴的所有模塊版本,保證今后項(xiàng)目依賴的版本不會(huì)被篡改搞莺。間接依賴的包的哈希值也會(huì)被保存痛阻。

go.sum 文件中有兩種 hash 的形式:

  1. h1:<hash> 將目標(biāo)模塊版本的 zip 文件開包后,針對(duì)所有包內(nèi)文件依次進(jìn)行 hash腮敌,然后再把它們的 hash 結(jié)果按照固定格式和算法組成總的 hash 值,如果不存在俏扩,表示可能依賴的庫(kù)用不上
  2. xxx/go.mod h1.<hash> 表示 go.mod 文件做的 hash

# 將目標(biāo)模塊版本的 zip 文件開包后糜工,針對(duì)包內(nèi)所有文件依次進(jìn)行 hash,然后再將 它們的 hash 結(jié)果匯總組成 hash
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=

# 針對(duì) go.mod 文件的 hash 值
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=

go get 拉取命令

下載的模塊會(huì)被放置于 $GOPATH/pkg/mod 目錄中

命令 作用
go get 拉取依賴录淡,會(huì)進(jìn)行指定性拉劝颇尽(更新),并不會(huì)更新所依賴的其它模塊嫉戚。(如果本地已存在要下載的包刨裆,將會(huì)直接使用本地已存在的包)
go get -u 更新現(xiàn)有的依賴,會(huì)強(qiáng)制更新它所依賴的其它全部模塊彬檀,不包括自身帆啃。
go get -u -t ./… 更新所有直接依賴和間接依賴的模塊版本,包括單元測(cè)試中用到的窍帝。
go get golang.org/x/text@latest 拉取最新的版本努潘,若存在 tag,則優(yōu)先使用。
go get golang.org/x/text@master 拉取 master 分支的最新 commit疯坤。
go get golang.org/x/text@v0.3.2 拉取 tag 為 v0.3.2 的 commit报慕。
go get golang.org/x/text@342b2e 拉取 hash 為 342b231 的 commit,最終會(huì)被轉(zhuǎn)換為 v0.3.2压怠。

go get 子參數(shù)說(shuō)明

子命令 描述
-d 僅下載眠冈,不安裝
-f 和 -u 配合,強(qiáng)制更新菌瘫,不檢查是否過(guò)期
-t 下載測(cè)試代碼所需的依賴包
-u 更新包蜗顽,包括他們的依賴項(xiàng)
-v 輸出詳細(xì)信息
insecure 使用 http 等非安全協(xié)議

修改項(xiàng)目模塊的版本依賴關(guān)系


go mod edit -replace=<老版本>=<需要替換的版本>

# 比如
go mod edit -replace=demo-package@v1.0.0=demo-package@v2.0.0

go list 命令以及參數(shù)

go list -m -u all
參數(shù) 作用
-f 用于查看對(duì)應(yīng)依賴結(jié)構(gòu)體中的指定的字段,其默認(rèn)值就是 {{.ImportPath}}突梦,也就是導(dǎo)入路徑诫舅,因此我們一般不需要進(jìn)行調(diào)整
-json 顯示的格式,若不指定該選項(xiàng)宫患,則會(huì)一行行輸出刊懈。
-u 顯示能夠升級(jí)的模塊信息
-m 顯示當(dāng)前項(xiàng)目所依賴的全部模塊

比如查看 gin 框架的版本

go list -m -versions -json github.com/gin-gonic/gin

輸出如下:

{
    "Path": "github.com/gin-gonic/gin",
    "Version": "v1.7.7",
    "Versions": [
        "v1.1.1",
        "v1.1.2",
        "v1.1.3",
        "v1.1.4",
        "v1.3.0",
        "v1.4.0",
        "v1.5.0",
        "v1.6.0",
        "v1.6.1",
        "v1.6.2",
        "v1.6.3",
        "v1.7.0",
        "v1.7.1",
        "v1.7.2",
        "v1.7.3",
        "v1.7.4",
        "v1.7.6",
        "v1.7.7"
    ],
    "Time": "2021-11-24T13:54:13Z",
    "Dir": "/Users/pudongping/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7",
    "GoMod": "/Users/pudongping/go/pkg/mod/cache/download/github.com/gin-gonic/gin/@v/v1.7.7.mod",
    "GoVersion": "1.13"
}

私有庫(kù)使用 Go Modules 時(shí)

  • 需要將 GOPRIVATE 環(huán)境變量設(shè)置成你私有庫(kù)的域名
# GO111MODULE 設(shè)置成 on 或者 auto 都行
GO111MODULE="auto"
# GOPROXY 最好設(shè)置成國(guó)內(nèi)鏡像地址
GOPROXY="https://goproxy.cn,direct"
# GOPRIVATE 一定要設(shè)置成你的私有庫(kù)域名,比如
GOPRIVATE="gitlab.xxx.com"
  • 然后執(zhí)行以下命令即可娃闲。注意:前提是你能夠通過(guò) ssh 公鑰拉取代碼
# 以下假設(shè)我私有 git 倉(cāng)庫(kù)地址為 gitlab.xxx.com:2222
# 那么則需要調(diào)整為

cat << EOF >> ~/.gitconfig
[url "ssh://git@gitlab.xxx.com:2222"]
        insteadOf = https://gitlab.xxx.com
EOF

# 或者執(zhí)行(效果都是一樣的)
git config --global url."ssh://git@gitlab.xxx.com:2222".insteadof "https://gitlab.xxx.com"
  • 測(cè)試一下下載一個(gè)包
# 僅僅作為示范虚汛,此地址根本就不存在
go get -v gitlab.xxx.com/utils/arrayx
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市皇帮,隨后出現(xiàn)的幾起案子卷哩,更是在濱河造成了極大的恐慌,老刑警劉巖属拾,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件将谊,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡渐白,警方通過(guò)查閱死者的電腦和手機(jī)尊浓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)纯衍,“玉大人栋齿,你說(shuō)我怎么就攤上這事〗笾睿” “怎么了瓦堵?”我有些...
    開封第一講書人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)歌亲。 經(jīng)常有香客問(wèn)我菇用,道長(zhǎng),這世上最難降的妖魔是什么陷揪? 我笑而不...
    開封第一講書人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任刨疼,我火速辦了婚禮泉唁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘揩慕。我一直安慰自己亭畜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開白布迎卤。 她就那樣靜靜地躺著拴鸵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蜗搔。 梳的紋絲不亂的頭發(fā)上劲藐,一...
    開封第一講書人閱讀 52,255評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音樟凄,去河邊找鬼聘芜。 笑死,一個(gè)胖子當(dāng)著我的面吹牛缝龄,可吹牛的內(nèi)容都是我干的汰现。 我是一名探鬼主播,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼叔壤,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼瞎饲!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起炼绘,我...
    開封第一講書人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤嗅战,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后俺亮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體驮捍,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年脚曾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了东且。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡斟珊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出富纸,到底是詐尸還是另有隱情囤踩,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布晓褪,位于F島的核電站堵漱,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏涣仿。R本人自食惡果不足惜勤庐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一示惊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧愉镰,春花似錦米罚、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至碗降,卻和暖如春隘竭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背讼渊。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工动看, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人爪幻。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓堤器,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親楞遏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蔫巩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • Modules 先把最重要的說(shuō)了,關(guān)于modules的最新詳細(xì)信息可以執(zhí)行命令go help modules或者查...
    winlinvip閱讀 1,549評(píng)論 0 0
  • 參考一文搞懂 Go Modules 前世今生及入門使用[https://www.cnblogs.com/wongb...
    合肥黑閱讀 840評(píng)論 0 1
  • 舊項(xiàng)目遷移叶组,打算使用GO Modules 作為依賴管理拯田。 go版本 1.12 私人依賴包,如何處理 1. 創(chuàng)建模塊...
    起名好難_b30f閱讀 4,006評(píng)論 1 11
  • File types(文件類型) go命令檢查目錄中特定文件的集合甩十。它根據(jù)文件的擴(kuò)展名表示要檢查的文件船庇。這些擴(kuò)展名...
    Cxb168閱讀 1,745評(píng)論 0 0
  • 什么是Go Modules? Go modules 是 Go 語(yǔ)言的依賴解決方案,發(fā)布于 Go1.11侣监,成長(zhǎng)于 G...
    舍是境界閱讀 1,720評(píng)論 0 1