前言

随着 Go 语言的深入使用,其依赖管理机制也一直是各位 Gopher 热衷于探讨的话题。Go 语言的源码依赖可通过 go get 命令来获取,但自动化程度不高,于是官方提供了 Dep 这样的自动化批量管理依赖的工具。虽然 Go 语言的依赖管理在很多方面还是不如人意,但整个体系正在日趋完善,本篇就将从最基本的依赖管理场景出发,一同探讨 Go 语言依赖管理的一些最佳实践。

Go 依赖管理的基本思路

在 Go 语言中,我们通过 go get 命令将 GitHub 或者 Google Code 上的代码下载到本地指定目录,然后在开发代码中通过 import 的形式引用本地的代码。
Go 包管理机制深入分析

Go 语言可以通过直接分析代码中的 import 语句来查询依赖关系。go get 命令在执行时,就会自动解析 import 来安装所有的依赖。那么下载的依赖在本地是如何存储的呢?

这里就涉及到 Go 语言的 WORKSPACE 概念,简单来说就是通过 GOPATH 环境变量来设置 Go 代码的位置。一般来说,GOPATH 目录下会包含 pkg、src 和 bin 三个子目录,这三个目录各有用处。

bin 目录用来放置编译好的可执行文件,为了使得这里的可执行文件可以方便的运行,在 shell 中设置PATH变量。

src 目录用来放置代码源文件,在进行 import 时,是使用这个位置作为根目录的。自己编写的代码也应该放在这下面,不同的项目放在不同的目录下进行管理。

pkg 用来放置安装的包的链接对象(Object)的。这个概念有点类似于链接库,Go 会将编译出的可连接库放在这里,方便编译时链接。不同的系统和处理器架构的对象会在 pkg 存放在不同的文件夹中。

当项目在 src 目录下管理时,多个项目可能都会使用相同的依赖,如果每个项目都存一份依赖显然会带来大量的冗余,这里我们推荐一个设置 GOPATH 环境变量时的小技巧。
Go 包管理机制深入分析

这样第三方包就会默认放置在第一个路径中,而你可以在第二个路径下编写自己的代码,多个项目共享一份依赖。

dep - 官方 Go 依赖管理工具

dep 是 Go 语言官方提供的依赖管理工具,跟其他依赖管理工具类似,都是通过一个文件描述依赖的坐标信息,然后批量管理(下载、升级等)依赖包(源码)。dep 是一个开源项目, 大家可以在 https://github.com/golang/dep 了解详细信息,其安装方式大家可以参考官方说明,这里我们主要介绍其使用。

基本操作
通过 dep init 命令来初始化,会创建Gopkg.lock,Gopkg.toml文件和一个空的vendor目录。

我们在代码中通过 import 命令添加依赖后,通过 dep ensure 就可以下载依赖到本地 $GOPATH/src 目录下。

main.go
Go 包管理机制深入分析_第1张图片

Gopkg.lock

Go 包管理机制深入分析_第2张图片
通过 dep status 我们可以查看当前依赖引用的情况
Go 包管理机制深入分析

另外有一个 dep check 命令来检查是否存在依赖被引用,但是代码中并没有使用的情况,Go 语言对于依赖的引用比较严格,不允许引用了但是没使用的情况。从软件安全的角度考虑,这是一个很好的实践,避免引入一些安全风险。
Go 包管理机制深入分析

当然,这种时候我们就需要移除本地依赖,最好不要手动删除vendor中的内容,而是通过 dep ensure -update 命令来移除。

从 dep 的目录结构,我们可以分析出 dep 的基本工作思路:

这里面有两个关键的步骤:

解析依赖

从当前项目的 import 文件中解析出整个工程的依赖情况,并结合 Gopkg.toml 定义的规则,然后将依赖关系输出给 Gopkg.lock,注意这个 lock 文件最好不要手动修改。

获取依赖

通过 Gopkg.lock 了解整个依赖关系之后,将依赖的具体内容拉取下来放到 vendor 目录中,然后执行 Go build 时从本地的 vendor 读取依赖并完成构建。

这一些都是在 dep ensure 时完成的,其实在执行这个命令时还可以传参数,最主要的是 -no-vendor 和 -vendor-only 这两个参数。

-no-vendor 参数只会导致运行 resolve 函数,结果是创建一个新的Gopkg.lock 文件,不会更新 vendor;而 -vendor-only 参数将跳过 resolve 并仅运行 vendoring 函数,导致 vendor/ 从已存在的Gopkg.lock 重新更新。

关于 dep 更多深入内容,可以参考

https://golang.github.io/dep/docs/introduction.html

总结

Go dep 目前是一款比较好用的依赖管理工具,很多比较大型的项目都在使用,从中可以学习到依赖管理的一些基本思路,对于理解其他语言,比如 NPM 的依赖管理模型也是比较有好处的。
**
更多精彩内容可以专注我们的在线课堂

微信搜索公众号:jfrogchina 获取课程通知**