Go外部依赖包从vendor、$GOPATH和$GOPATH/pkg/mod下的查找顺序
vendor
vendor
概念最早是由Keith提出,用来存放依赖包。在版本1.5出现。例如gb项目提供了一个名为gsftp
的示例项目,它有一个gsftp
程序,在标准库之外有三个依赖项。golang.org/x/crypto/ssh
, golang.org/x/crypto/ssh/agent
和github.com/pkg/sftp
。按vendor
概念调整的目录结构如下:
$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
的引用如下所示,看起来和平时的引用没什么区别。
import (
...
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent"
"github.com/pkg/sftp"
)
因为github.com/constabulary/example-gsftp/vendor/golang.org/x/crypto/ssh
存在,且正在编译的文件位于以github.com/constabulary/example-gsftp
为根的子树中。则导入语句import "golang.org/x/crypto/ssh"
,编译好像是import "github.com/constabulary/example-gsftp/vendor/golang.org/x/crypto/ssh"
,只不过这种较长的形式从未写过。
因此github.com/constabulary/example-gsftp
中的源代码取决于vendor
中有关golang.org/x/crypto/ssh
的拷贝副本, 而不是$GOPATH
中的其他地方。
vendor的层级搜索
规则是:
- 从引用文件所在的
vendor
路径下面搜索, - 如果没有找到,那么从上层目录的
vendor
路径下面搜索, - 直到
src
的vendor
路径下面搜索。
modules
Go 1.11版本支持临时环境变量GO111MODULE
,通过该环境变量来控制依赖包的管理方式。当GO111MODULE
的值为on
时,那么就会使用modules
功能,这种模式下,$GOPATH
不再作为build时导入的角色,依赖包会存放在$GOPATH/pkg/mod
目录下。工程中的依赖包也会从此目录下查找。有关该功能的介绍,可以看Go1.1.1新功能module的介绍及使用。
查找顺序
GO111MODULE=off
时,如果一个包在vendor
和$GOPATH
下都存在,那么使用顺序为:
- 优先使用
vendor
目录下面的包, - 如果
vendor
下面没有搜索到,再搜索$GOPATH/src
下面的包, - 如果
$GOPATH
下面没有搜索到,那么搜索$GOROOT/src
下面的包, - 要么完整使用
vendor
下面的包,要么完整使用$GOPATH
下面的包,不会混合使用。
参考文章