golang沒有官方最佳管理方案,在go的世界里存在大量的自制解決方案。
go語言的包是沒有中央庫統一管理的,通過使用go get
命令從遠程代碼庫(github.com,goolge code 等)拉取,直接跳過中央版本庫的約束,讓代碼的拉取直接基於源代碼版本控制庫開發者間的協同直接依賴於源代碼的版本控制。
這就直接去除了庫版本的概念。沒有明顯的包版本標識,官方的建議是把外部依賴的代碼全部復制到自己可控的源代碼庫中,進行統一管理,從而做到對依賴包的可控管理。
下面是一些推薦的版本管理工具:
版本管理工具
1.5版本的vendor目錄特性后,官方wiki推薦了多種支持這種特性的包管理工具如:
- godep
- gv
- gvt
- glide
- govendor
我們在這里推薦使用glide
glide簡介
glide(官網)是一個golang項目的包管理工具,非常方便快捷,一般只需要2-3個命令就可以將go依賴包自動下載並
歸檔到vendor的目錄中。
安裝
下面提供了幾種安裝途徑:
- 1.命令行安裝
curl https://glide.sh/get | sh
- 2.下載release
https://github.com/Masterminds/glide/releases
- 3.使用brew安裝
brew install glide
- 4.使用go get安裝(推薦方法)
go get -u github.com/Masterminds/glide
使用
1 偵測項目依賴
#進入到項目目錄
> cd $GOPATH/src/demo
#glide初始化,初始化配置文件glide.yaml
> glide init
運行上面的命令后,會生成配置文件glide.yaml
,其中包含了依賴庫的信息,比如版本號,大致格式如下:
package: github.com/MangoDowner/archive
import:
- package: github.com/astaxie/beego
version: v1.11.1
- package: github.com/fsnotify/fsnotify
version: v1.4.7
運行過程中還可能出現一些交互信息,咨詢依賴版本之類的,比如
[INFO] Here are some suggestions...
[INFO] The package github.com/astaxie/beego appears to have Semantic Version releases (http://semver.org).
[INFO] The latest release is v1.11.1. You are currently not using a release. Would you like
[INFO] to use this release? Yes (Y) or No (N)
2 更新項目依賴
# glide加載依賴包,自動歸檔到vendor目錄
glide up -v
glide 會生成一個glide.lock
文件,該文件包含了完整的依賴樹信息.
**注意: 此處不包括此文件的詳細信息,因為不應手動編輯此文件。 **
為什么這里會有一個 -v
?
--strip-vendor
或者 -v
標識都是為了解決下面的問題.
3. 扁平化依賴關系
glide將所有的依賴關系都遷入項目的頂級vendor文件夾中,原因有二:
- 1.所有引入位置都會編譯進可執行文件.如果同樣的依賴被三個
vendor
目錄引入,
就要變異三次.這會導致編譯文件變得臃腫. - 2.同樣依賴包,如果在不同的位置,就會生成不同的變量實例.即使他們有着相同的版本.
go把他們看成是不同的包,因為他們在不同的位置.
這對於數據庫驅動/日志等其他東西來說都是個大問題.
比如下面的依賴:
- $GOPATH/src/github.com/mattfarina/golang-broken-vendor
- foo.go
- vendor/
- a/
- b/
- vendor/a/
這樣的代碼就不能運行
func main() {
var it a.A
it = "foo"
b.Do(it)
}
報錯信息:
$ GO15VENDOREXPERIMENT=1 go build
./foo.go:12: cannot use it
(type "github.com/mattfarina/golang-broken-vendor/vendor/a".A) as type
"github.com/mattfarina/golang-broken-vendor/vendor/b/vendor/a".
A in argument to b.Do
3 增加項目依賴
可以使用get
命令
> glide get github.com/Masterminds/semver
也可以帶上版本
> glide get github.com/Masterminds/semver#~1.2.0
#
用來隔離依賴名稱和版本號.
get
命令和go get
類似,只是前者將依賴拉入vendor
目錄,
而后者拉入GOPATH
相應目錄.
配置文件
配置文件包含了項目的信息還有依賴包
package: github.com/Masterminds/glide
homepage: https://masterminds.github.io/glide
license: MIT
owners:
- name: Matt Butcher
email: technosophos@gmail.com
homepage: http://technosophos.com
- name: Matt Farina
email: matt@mattfarina.com
homepage: https://www.mattfarina.com
ignore:
- appengine
excludeDirs:
- node_modules
import:
- package: gopkg.in/yaml.v2
- package: github.com/Masterminds/vcs
version: ^1.2.0
repo: git@github.com:Masterminds/vcs
vcs: git
- package: github.com/codegangsta/cli
version: f89effe81c1ece9c5b0fda359ebd9cf65f169a51
- package: github.com/Masterminds/semver
version: ^1.0.0
testImport:
- package: github.com/arschles/assert
package
:GOPATH
位置下的頂層包.者用來確保不會在頂層包級再次引入.homepage
: 一般用來指明查看包或者和應用更多內容的地方.比如說, http://k8s.ioowners
: 項目所有人的列表.可以用來聯系所有人ignore
: 用來讓glide忽略引入.一般是包名而不是目錄名.excludeDirs
: 要從依賴項掃描中排除的本地代碼庫目錄列表。import
: 要引入的包列表,包括:package
: 要引入的包名,而且是為唯一的必填項.包名和go tool引入的規則一樣. 也就是說:- 包名映射到遠程的VCS地址,比如.git, .bzr, .hg, 或者.svn.比如
example.com/foo/pkg.git/subpkg
- GitHub, BitBucket, Launchpad, IBM Bluemix Services還有 Go on Google Source是特殊情形,不需要vcs后綴.
- 包名映射到遠程的VCS地址,比如.git, .bzr, .hg, 或者.svn.比如
version
: 語義版本/語義版本范圍/分支/tag或提交id,都可以使用repo
: 如果包名不是包的位置,或者屬於私有庫.這可以從repo指定的位置拉取代碼並放入包名指定的位置里面去.
這樣就可以支持fork,而且可以解決golang.org代碼被牆的問題.
vcs
:可以使用的VCS,比如說 git, hg, bzr, 或者 svn. 只有無法從名稱偵測到類型的時候才需要.subpackages
: 倉庫中被使用的包的記錄,也就是說不包括那些沒被使用的包.os
: 操作系統列表.如果設置了,它會將當前runtime操作系統與指定的操作系統進行比較,只在存在匹配項時獲取依賴項.
名稱和go build
以及GOOS
環境變量中使用的相同
testImport
:在tests
中使用,並且未在import中列出包列表.他們和import下面列出的包有着相同的細節.
下面提供一些常用的命令:
常用命令
glide create (別名init)
初始化新的workspace,還會創建glide.yaml文件,同時嘗試猜測要放入其中的包和版本。
如果您的項目正在使用godep,它將使用那里指定的版本。
glide很智能,可以掃描代碼庫並檢測正在使用的導入,無論它們是否與其他包管理器一起指定。
glide get [包名]
你可以使用該指令來將包下載到你的vendor
目錄下,glide還會將包放入你的glide.yaml
文件中去.
$ glide get github.com/Masterminds/cookoo
glide update (別名up)
下載glide.yaml
文件中列出的所有庫,並將他們放到vendor
目錄下.
如果要解決前文所說的那個多次引入vendor目錄,請使用-v
標志,即:
glide update -v
glide install
如果你想要安裝glide.lock
中指定的版本:
$ glide install
glide novendor (別名nv)
當你運行go test
的時候,比如go test ./...
時,go會把你依賴庫的test也進行一遍,這不是我們想要的.
這時候就可以使用該命令,只對項目本身的tests進行處理.
go test $(glide novendor)
glide list
這個命令會按序列出項目引入的所有包:
$ glide list
INSTALLED packages:
vendor/github.com/Masterminds/cookoo
vendor/github.com/Masterminds/cookoo/fmt
vendor/github.com/Masterminds/cookoo/io
vendor/github.com/Masterminds/cookoo/web
vendor/github.com/Masterminds/semver
vendor/github.com/Masterminds/vcs
vendor/github.com/codegangsta/cli
vendor/gopkg.in/yaml.v2
glide mirror
鏡像用原始鏡像的另一個位置替換倉庫位置力。
如果希望為持續集成(CI)系統加入緩存,或者希望在本地位置處理依賴項時,這就很有用了。
鏡像存儲在你的
GLIDE_HOME
目錄的mirrors.yaml
目錄里
其包含的三個自命令為list
, set
, 還有 remove
.
set命令:
glide mirror set [original] [replacement]
# 或者
glide mirror set [original] [replacement] --vcs [type]
比如說:
glide mirror set https://github.com/example/foo https://git.example.com/example/foo.git
# 又或者
glide mirror set https://github.com/example/foo file:///path/to/local/repo --vcs git
remove命令:
glide mirror remove [original]
比如說:
glide mirror remove https://github.com/example/foo
參考文章:
Golang包管理工具glide簡介
Glide: Vendor Package Management for Go