Go外部依賴包從vendor,$GOPATH和$GOPATH/pkg/mod查找順序
vendor
vendor概念最早是由Keith提出,用來(lái)存放依賴包。在版本1.5出現(xiàn)。例如gb項(xiàng)目提供了一個(gè)名為gsftp的示例項(xiàng)目,它有一個(gè)gsftp程序,在標(biāo)準(zhǔn)庫(kù)之外有三個(gè)依賴項(xiàng)。golang.org/x/crypto/ssh, golang.org/x/crypto/ssh/agent和github.com/pkg/sftp。
按vendor概念調(diào)整的目錄結(jié)構(gòu)如下:
$GOPATH | src/ | | github.com/constabulary/example-gsftp/ | | | cmd/ | | | | gsftp/ | | | | | main.go | | | vendor/ | | | | github.com/pkg/sftp/ | | | | golang.org/x/crypto/ssh/ | | | | | agent/
文件github.com/constabulary/example-gsftp/cmd/gsftp/main.go的引用如下所示,看起來(lái)和平時(shí)的引用沒什么區(qū)別。
import ( ... "golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh/agent" "github.com/pkg/sftp" )
因?yàn)間ithub.com/constabulary/example-gsftp/vendor/golang.org/x/crypto/ssh存在,且正在編譯的文件位于以github.com/constabulary/example-gsftp為根的子樹中。則導(dǎo)入語(yǔ)句import "golang.org/x/crypto/ssh",編譯好像是import "github.com/constabulary/example-gsftp/vendor/golang.org/x/crypto/ssh",只不過(guò)這種較長(zhǎng)的形式從未寫過(guò)。
因此github.com/constabulary/example-gsftp中的源代碼取決于vendor中有關(guān)golang.org/x/crypto/ssh的拷貝副本, 而不是$GOPATH中的其他地方。
vendor的層級(jí)搜索
規(guī)則是:
從引用文件所在的vendor路徑下面搜索,
如果沒有找到,那么從上層目錄的vendor路徑下面搜索,
直到src的vendor路徑下面搜索。
modules
Go 1.11版本支持臨時(shí)環(huán)境變量GO111MODULE,通過(guò)該環(huán)境變量來(lái)控制依賴包的管理方式。當(dāng)GO111MODULE的值為on時(shí),那么就會(huì)使用modules功能,這種模式下,$GOPATH不再作為build時(shí)導(dǎo)入的角色,依賴包會(huì)存放在$GOPATH/pkg/mod目錄下。工程中的依賴包也會(huì)從此目錄下查找。
有關(guān)該功能的介紹,可以看Go1.1.1新功能module的介紹及使用。
查找順序
GO111MODULE=off時(shí),如果一個(gè)包在vendor和$GOPATH下都存在,那么使用順序?yàn)椋?/p>
優(yōu)先使用vendor目錄下面的包,
如果vendor下面沒有搜索到,再搜索$GOPATH/src下面的包,
如果$GOPATH下面沒有搜索到,那么搜索$GOROOT/src下面的包,
要么完整使用vendor下面的包,要么完整使用$GOPATH下面的包,不會(huì)混合使用。
補(bǔ)充:Go 語(yǔ)言編程 — go mod 依賴包管理
使用 go mod
go mod 的子指令
go mod 依賴包管理
Golang 將 Modules(模塊)定義為 “源代碼交付和版本控制的單元”。
go mod 是 Golang 1.11 版本引入的依賴包管理工具,替換舊的基于 GOPATH 的依賴包管理方式。GOPATH 不再需要包含 src 子目錄,使用 go.mod 方式管理的依賴包都被下載到了 $GOPATH/pkg/mod 目錄。
有了 go mod 之后,每個(gè)項(xiàng)目(源代碼目錄)就是一個(gè) Module,只要其中包含了 go.mod 文件。go mod 指令和 go.mod 文件用于記錄和解析模塊之間的依賴性。
go.mod 文件一旦創(chuàng)建后,它的內(nèi)容將會(huì)被 go toolchain(工具鏈)完全掌控,比如:執(zhí)行 go get、go build、go mod 等指令時(shí),會(huì)自動(dòng)修改和維護(hù) go.mod 文件。
除了 go.mod 之外,go 指令還維護(hù)了一個(gè) go.sum 文件,其中包含特定模塊版本內(nèi)容的加密哈希。go 指令使用 go.sum 文件來(lái)確保這些模塊的哈希值,以確保項(xiàng)目所依賴的模塊不會(huì)出現(xiàn)意外更改。
go.mod 和 go.sum 都應(yīng)該應(yīng)用于版本控制。 并且 go.sum 不需要手工維護(hù),所以可以不用太關(guān)注。
使用 go mod
使用 Go Modules 需要配置 GO111MODULE 環(huán)境變量,GO111MODULE 有三個(gè)值:off、on 和 auto(默認(rèn)值):
GO111MODULE=off:關(guān)閉 Go Modules,沿用舊版本的 GOPATH 方式,項(xiàng)目的依賴包依舊在 vendor 目錄或者 $GOPATH/src 目錄下進(jìn)行查找。
GO111MODULE=on:開啟 Go Modules,項(xiàng)目的依賴包記錄在 go.mod 文件中。
GO111MODULE=auto:go 指令根據(jù)當(dāng)前目錄來(lái)決定是否啟用 Modules 功能。
當(dāng)項(xiàng)目處于 GOPATH/src 內(nèi),則會(huì)使用 GOPATH/src 的依賴包。
當(dāng)項(xiàng)目處于 GOPATH/src 外,則使用 go.mod 里 require 聲明的依賴包。
使用 go.mod 的流程:
在 $GOPATH/src 目錄之外創(chuàng)建 Golang 項(xiàng)目。
初始化項(xiàng)目的 go.mod 文件。
$ go mod init <projectNmae>
注意,項(xiàng)目下屬的子目錄是不需要再次 init 的,整個(gè)項(xiàng)目的依賴都會(huì)組織在根目錄的 go.mod 文件里。
導(dǎo)入外部包:
package main import ( "fmt" "github.com/gohouse/gorose" ) func main() { fmt.Println("hello world!") }
運(yùn)行程序時(shí),會(huì)自動(dòng)下載依賴包并更新 go.mod 文件:
$ go run hello.go go: finding module for package github.com/gohouse/gorose go: downloading github.com/gohouse/gorose v1.0.5 go: found github.com/gohouse/gorose in github.com/gohouse/gorose v1.0.5 go: finding module for package github.com/gohouse/converter go: downloading github.com/BurntSushi/toml v0.3.0 go: downloading github.com/gohouse/converter v0.0.3 go: found github.com/gohouse/converter in github.com/gohouse/converter v0.0.3 go: downloading github.com/go-sql-driver/mysql v1.4.0 # command-line-arguments ./hello.go:5:5: imported and not used: "github.com/gohouse/gorose"
檢查 go.mod 文件中自動(dòng)更新的依賴清單:
module hello go 1.14 require ( github.com/gohouse/converter v0.0.3 // indirect github.com/gohouse/gorose v1.0.5 // indirect )
其中 require 是一個(gè)關(guān)鍵字,此外還有 module、replace 和 exclude:
module 語(yǔ)句:指定模塊的名字(路徑)。
require 語(yǔ)句:指定的依賴模塊。
replace 語(yǔ)句:可以替換依賴項(xiàng)模塊。
exclude 語(yǔ)句:可以忽略依賴項(xiàng)模塊。
另外,上述的 v0.0.3 就是依賴包 converter 的版本。如果沒有在 go.mod 指定版本,go 指令就會(huì)自動(dòng)下載代碼中的依賴的最新版本。否則,go 指令會(huì)根據(jù) require 語(yǔ)句的路徑和版本進(jìn)行下載。指定版本時(shí)也可以用 latest,表示下載最新的版本。
replace 語(yǔ)句常用于依賴包實(shí)際路徑變更的場(chǎng)景中,例如:
replace golang.org/x/text => github.com/golang/text latest
如此的,在這種情況下依賴包的維護(hù)會(huì)變得更簡(jiǎn)單。
還需要注意 go.mod 中的 module hello 這一條語(yǔ)句,因?yàn)楫?dāng)前項(xiàng)目已經(jīng)不在 $GOPATH/src 內(nèi)了,所以 module hello 標(biāo)注了項(xiàng)目 “根” 的路徑,以此來(lái)作為項(xiàng)目中其他包的根路徑。
go mod 的子指令
初始化一個(gè) Module:
go mod init <project_name>
下載項(xiàng)目依賴的 modules 到本地 Cache:
# 在項(xiàng)目目錄下執(zhí)行
go mod download
注:目前所有模塊版本數(shù)據(jù)均緩存在 $GOPATH/pkg/mod 和 $GOPATH/pkg/sum 下。
編輯 go.mod 文件,選項(xiàng)有 -json、-require 和 -exclude:
go mod edit # e.g. go mod edit -replace=golang.org/x/crypto@v0.0.0=github.com/golang/crypto@latest
以文本模式打印模塊需求圖:
go mod graph
刪除錯(cuò)誤或者不使用的 Modules:
go mod tidy
生成 Vendor 目錄:
go mod vendor
驗(yàn)證依賴是否正確:
go mod verify
查找依賴:
go mod why
清理 Modules 緩存:
go clean -modcache
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
Go語(yǔ)言設(shè)置JSON的默認(rèn)值操作
這篇文章主要介紹了Go語(yǔ)言設(shè)置JSON的默認(rèn)值操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12Golang設(shè)計(jì)模式之單例模式詳細(xì)講解
單例模式很容易記住。就像名稱一樣,它只能提供對(duì)象的單一實(shí)例,保證一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)全局訪問(wèn)該實(shí)例的方法。本文就來(lái)聊聊Go語(yǔ)言中的單例模式,感興趣的小伙伴可以了解一下2023-01-01Golang map實(shí)踐及實(shí)現(xiàn)原理解析
這篇文章主要介紹了Golang map實(shí)踐以及實(shí)現(xiàn)原理,Go 語(yǔ)言中,通過(guò)哈希查找表實(shí)現(xiàn) map,用鏈表法解決哈希沖突,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2022-06-06VSCode安裝go相關(guān)插件失敗的簡(jiǎn)單解決方案
這篇文章主要給大家介紹了關(guān)于VSCode安裝go相關(guān)插件失敗的簡(jiǎn)單解決方案,VSCode是我們開發(fā)go程序的常用工具,最近安裝的時(shí)候遇到了些問(wèn)題,需要的朋友可以參考下2023-07-07go語(yǔ)言中sort包的實(shí)現(xiàn)方法與應(yīng)用詳解
golang中也實(shí)現(xiàn)了排序算法的包sort包,所以下面這篇文章主要給大家介紹了關(guān)于go語(yǔ)言中sort包的實(shí)現(xiàn)方法與應(yīng)用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11一文詳解Go語(yǔ)言fmt標(biāo)準(zhǔn)庫(kù)的常用占位符使用
這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言中fmt標(biāo)準(zhǔn)庫(kù)的常用占位符及其簡(jiǎn)單使用,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Go語(yǔ)言有一定的幫助,需要的可以參考一下2022-12-12