Golang包管理工具govendor的使用

1. govendor簡介

golang工程的依賴包經常使用go get命令來獲取,例如:go get github.com/kardianos/govendor ,會將依賴包下載到GOPATH的路徑下。

常用的依賴包管理工具有godep,govendor等,在Golang1.5之後,Go提供了 GO15VENDOREXPERIMENT 環境變量(Go 1.6版本默認開啓該環境變量),用於將go build時的應用路徑搜索調整成爲 當前項目目錄/vendor 目錄方式。通過這種形式,我們可以實現類似於 godep 方式的項目依賴管理。

2. 安裝與使用

2.1. 安裝

go get -u -v github.com/kardianos/govendor

2.2 使用

#進入到項目目錄
cd /home/gopath/src/mytool

#初始化vendor目錄
govendor init

#查看vendor目錄
[root@CC54425A mytool]# ls
commands  main.go  vendor  mytool_test.sh

#將GOPATH中本工程使用到的依賴包自動移動到vendor目錄中
#說明:如果本地GOPATH沒有依賴包,先go get相應的依賴包
govendor add +external
或使用縮寫: govendor add +e 

#Go 1.6以上版本默認開啓 GO15VENDOREXPERIMENT 環境變量,可忽略該步驟。
#通過設置環境變量 GO15VENDOREXPERIMENT=1 使用vendor文件夾構建文件。
#可以選擇 export GO15VENDOREXPERIMENT=1 或 GO15VENDOREXPERIMENT=1 go build 執行編譯
export GO15VENDOREXPERIMENT=1

2.3. 說明

govendor只是用來管理項目的依賴包,如果GOPATH中本身沒有項目的依賴包,則需要通過go get先下載到GOPATH中,再通過govendor add +external拷貝到vendor目錄中。Go 1.6以上版本默認開啓GO15VENDOREXPERIMENT環境變量。

2.4. 常用命令

常見的命令如下,格式爲 govendor COMMAND。

命令 功能
init 初始化 vendor 目錄
list 列出所有的依賴包
add 添加包到 vendor 目錄,如 govendor add +external 添加所有外部包
add PKG_PATH 添加指定的依賴包到 vendor 目錄
update 從 $GOPATH 更新依賴包到 vendor 目錄
remove 從 vendor 管理中刪除依賴
status 列出所有缺失、過期和修改過的包
fetch 添加或更新包到本地 vendor 目錄
sync 本地存在 vendor.json 時候拉去依賴包,匹配所記錄的版本
get 類似 go get 目錄,拉取依賴包到 vendor 目錄

3.go mod

Go.mod是Golang1.11版本新引入的官方包管理工具用於解決之前沒有地方記錄依賴包具體版本的問題,方便依賴包的管理。

Go.mod其實就是一個Modules,關於Modules的官方定義爲:

Modules是相關Go包的集合,是源代碼交換和版本控制的單元。go命令直接支持使用Modules,包括記錄和解析對其他模塊的依賴性。Modules替換舊的基於GOPATH的方法,來指定使用哪些源文件。

Modules和傳統的GOPATH不同,不需要包含例如src,bin這樣的子目錄,一個源代碼目錄甚至是空目錄都可以作爲Modules,只要其中包含有go.mod文件。

3.1首先將go的版本升級爲1.11以上

下載地址,目前我只會重新安裝…

3.2 設置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文件的目錄下面。

坑:我在win10的時候只有通過在CMD窗口下set GO111MODULE=on命令才能生效,網上的通過環境變量,和Powershell窗口都是不生效的!

3.3 go mod命令:

download    下載依賴的module到本地cache
edit        編輯go.mod文件
graph       打印模塊依賴圖
init        在當前文件夾下初始化一個新的module, 創建go.mod文件
tidy        增加丟失的module,去掉未用的module
vendor      將依賴複製到vendor下,注意依賴需要在import 中聲明後才能進行導入
verify      校驗依賴
why         解釋爲什麼需要依賴
go get ./...  命令可以查找出當前項目的依賴

將對應的包替換爲對應github上面的包

replace (
    golang.org/x/crypto => github.com/golang/crypto v0.0.0-20181127143415-eb0de9b17e85
    golang.org/x/net => github.com/golang/net v0.0.0-20181114220301-adae6a3d119a
)

使用本地包

require (
    modtest v0.0.0
)

replace (
    modtest v0.0.0 => ../modtest
)

打包命令

1.使用GOPATH模式進行打包

export GO111MODULE=off
export CGO_ENABLED=0
go build  -a -v -o app main.go

2.使用vendor目錄下包來進行打包

export GO111MODULE=on
export CGO_ENABLED=0
go build -mod=vendor -a -v -o app main.go

3.4 go.mod如何在項目中使用

1.首先我們要在GOPATH/src 目錄之外新建工程,或將老工程copy到GOPATH/src 目錄之外。

PS:go.mod文件一旦創建後,它的內容將會被go toolchain全面掌控。go toolchain會在各類命令執行時,比如go get、go build、go mod等修改和維護go.mod文件。

go.mod 提供了module, require、replace和exclude四個命令

module語句指定包的名字(路徑)
require語句指定的依賴項模塊
replace語句可以替換依賴項模塊
exclude語句可以忽略依賴項模塊

問題一:依賴的包下載到哪裏了?還在GOPATH裏嗎?
不在。
使用Go的包管理方式,依賴的第三方包被下載到了$GOPATH/pkg/mod路徑下。

問題二: 依賴包的版本是怎麼控制的?
在上一個問題裏,可以看到最終下載在GOPATH/pkg/modv1.0.5,GOPATH/pkg/mod 下的包中最後會有一個版本號 v1.0.5,也就是說,GOPATH/pkg/mod裏可以保存相同包的不同版本。

版本是在go.mod中指定的。如果,在go.mod中沒有指定,go命令會自動下載代碼中的依賴的最新版本,本例就是自動下載最新的版本。如果,在go.mod用require語句指定包和版本 ,go命令會根據指定的路徑和版本下載包,
指定版本時可以用latest,這樣它會自動下載指定包的最新版本;

問題三: 可以把項目放在$GOPATH/src下嗎?
可以。但是go會根據GO111MODULE的值而採取不同的處理方式,默認情況下,GO111MODULE=auto 自動模式

1.auto 自動模式下,項目在GOPATH/src使GOPATH/src裏會使用GOPATH/src的依賴包,在GOPATH/src使go.modrequire2.on1.12GOPATH/src外,就使用go.mod 裏 require的包 2.on 開啓模式,1.12後,無論在GOPATH/src裏還是在外面,都會使用go.mod 裏 require的包
3.off 關閉模式,就是老規矩。

問題三: 依賴包中的地址失效了怎麼辦?比如 golang.org/x/… 下的包都無法下載怎麼辦?
在go快速發展的過程中,有一些依賴包地址變更了。以前的做法:

1.修改源碼,用新路徑替換import的地址
2.git clone 或 go get 新包後,copy到$GOPATH/src裏舊的路徑下
無論什麼方法,都不便於維護,特別是多人協同開發時。
使用go.mod就簡單了,在go.mod文件裏用 replace 替換包,例如
replace golang.org/x/text => github.com/golang/text latest
這樣,go會用 github.com/golang/text 替代golang.org/x/text,原理就是下載github.com/golang/text 的最新版本到 $GOPATH/pkg/mod/golang.org/x/text下。

問題四: init生成的go.mod的模塊名稱有什麼用?
本例裏,用 go mod init hello 生成的go.mod文件裏的第一行會申明module hello
因爲我們的項目已經不在$GOPATH/src裏了,那麼引用自己怎麼辦?就用模塊名+路徑。

問題五:以前老項目如何用新的包管理
如果用auto模式,把項目移動到$GOPATH/src外
進入目錄,運行 go mod init + 模塊名稱
go build 或者 go run 一次

轉載:https://www.jianshu.com/p/ac06dcb34d39

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