本文出现了大量maven的内容,更适合java程序员阅读,如果你的语言做依赖管理的方案与maven差异很大,可能在有些地方会不理解
从很久之前go语言在依赖解决和管理方面方案的匮乏就被不少人诟病。光指望go get指令,很多事办不成。我也不清楚从什么时候开始,dep,这个官方的解决方案开始被推广了。从说明上看,不会早于go 1.8,从github的源代码上看,至少开源不会超过1年
官方对于dep的介绍是“dep is the official experiment, but not yet the official tool.” 但又说 “dep is safe for production use.”。我并没在实践中真实使用,但也做了不少试验,基本可以认定其稳定,且“知名”,未来如果有更好的依赖管理方案,十有八九也是上面加个UI的壳吧
当然还有一个问题摆在面前:jenkins似乎没有dep的插件?那只能靠手写脚本了
在往下看之前先确定你清楚两个术语:我们把 github.com/apodemakeles/ugo 这玩意叫project,这是一个github上的仓库,也代表一个项目,把github.com/apodemakeles/ugo/time 这玩意儿叫package,是project下面一个go 语言的包。current project表示当前你正在编写的项目
前置知识点
首先你要清楚,go中获取依赖包都是通过执行go get命令,通过解析代码中的import语句,去下载相应的源代码到$GOPATH/src下,然后再进行install,安装在$GOPATH/pkg下。所以你如果要对应maven中下载的java的jar包的话,那实际上等于go中的源码和一堆.a文件。go get的说明
但go get的问题是没有版本上的控制,今天你运行的代码,可能和明天在jenkins上生成的代码完全不一样
另外一个问题也是拜go语言的特性所赐,由于所有的依赖项必须在$GOPATH下有对应的源码和.a文件,所以在同一台机上的不同项目,没法使用同一依赖项的不同版本。难道你要在不同的项目编译时git checkout一下?
所以在go 1.5开始官方引入了go vendor机制,简单点说就是在原来的project目录下加一个vendor文件夹,源码都“照搬”到这里,目录结构不动。所有import优先使用vendor中的源码。这个口子一开,一时间第三方纷纷推出自己的依赖解决工具了,比如我以前用过的govendor。 go vendor的说明
dep一瞥
要使用dep,首先要去github下载dep源码,编译成本地的可执行文件。确保你的$GOPATH/bin在你的PATH中,这样就可以在命令行执行dep命令了。具体详见 github 和 dep官方文档 ,不在此赘述
随便建立一个项目,当然要在$GOPATH下,此时先不要写代码,至少不要import远程的依赖,执行
dep init
你能看到project路径下多了三个东西,一个vendor文件夹,这个未来要来放current project的远程依赖的源代码,一个Gopkg.toml文件,你可以暂时将其类比为pom文件,或者npm的package.json文件,还有一个Gopkg.lock文件,这是啥?
既然toml文件类似于pom或者package.json,那按照里面的注释,试着添加一个依赖项试试,比如像我一样
[[constraint]] name = "github.com/apodemakeles/ugo" version = "=0.1.0"
看起来意思是需要下载ugo这个project,并且限制版本为0.1.0,下面执行
dep ensure
这个指令类似于install,compile之类,就是根据依赖的配置内容,下载依赖,编译依赖。指令很快就执行完了,但什么也没发生?这就是我之前说“暂时”类比为pom文件的原因,dep中要结合toml和代码中的import语句,才会真的下载,编译依赖项。把下面的代码贴到项目中去
package main import ( "fmt" "github.com/apodemakeles/ugo/time" ) func main() { fmt.Println(utime.NowUnixTS()) }
重新执行dep ensure,你会看到vendor中有了源代码,而那个不知道是什么的lock文件里是这样的:
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. [[projects]] name = "github.com/apodemakeles/ugo" packages = ["time"] revision = "96e9671d8beda19466b4296a8939ebfe26210683" version = "v0.1.0" [solve-meta] analyzer-name = "dep" analyzer-version = 1 inputs-digest = "4b0b8768bb38a412e1bbfd9952fe578e6f5b1a7469e3f44e444d66ca0c7ffaf6" solver-name = "gps-cdcl" solver-version = 1
现在再正式解释toml文件和lock文件:
toml文件记录着current project依赖项project的约束,而并不是应该有哪些project,有哪些project还是要看import了哪些package。这个约束主要体现在到底要采用目标project的某个tag的版本(version),还是某个branch,或者是某个commit sha1(revision),后面我们会称其"type", 这三个对于一个constraint只能选一个。你可以试试去掉toml的内容,执行dep ensure,依旧可以下载文件到vendor,依旧会修改lock文件
实际上除了constraint,还有其他几个约束, 比较重要的有required,ignored,override,前两个本文不会重点说明,override会在后面重点说明。toml文件的说明
lock文件是工具生成的,你不应该手工编辑,lock文件的packages对应你import的内容,而revision(一定会有,和type无关)和version则为vendor中源码的真实反映。lock文件的说明
注意到version那项写的是"v0.1.0"了没有?这是我github上代码真正的tag,在toml文件中的约束忽略了首字母v,直接拉取了tag为v0.1.0的代码
接下来把toml中的version改为“=0.1.1” 试试,假设你需要