$ 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
另外,go build 和 go install 及 go run 的区别:
go install 是针对 package的,而 go build 和 go run 是针对某文件的。对于 go build 可以是任意文件,对于go run这个文件必须属于package main。
go build 编译package main时,生成的可执行文件在当前目录,而 go install 编译 package main 时,生成的可执行文件在项目的bin目录下。
go build 和 go install 编译普通package时(非package main),生成的库都在项目的pkg目录下。
go run 只可以编译包含main()函数的那个.go文件,且立即执行文件。
go build 用于编译我们指定的源码文件或代码包以及它们的依赖包。,但是注意如果用来编译非命令源码文件(即非可执行文件),即库源码文件,go build 执行完是不会产生任何结果的。这种情况下,go build 命令只是检查库源码文件的有效性,只会做检查性的编译,而不会输出任何结果文件。
注意,不管是以go build 或者 go install 还是 go run 的方式来编译glide所管理的项目,所有的文件都必须位于其相应的package里,不允许某文件不位于任何package里,不然编译不会成功。以下面的projectDir项目为例,hello.go属于main package,如果将它移动到src下(不属于任何目录),此时用go build、go install 及 go run 都编译不成功,提示找不到imported package(引用的外部package,也即vendor里的package)。
对于上面的项目,使用glide来管理的话,项目目录结构为:
这种最标准方法的好处是在任何目录里(切换到 /tmp 目录,自己试试),都可以使用如下编译方法来编译任何项目:
go build projectDir/local/helloDir 或
go build projectDir/local/helloDir/hello.go 或
go install projectDir/local/helloDir 或
go run local/helloDir/hello.go 或 (先cd 到projectDir目录)
go run helloDir/hello 或 (先cd 到projectDir/local目录)
go run hello (先cd 到projectDir/local/helloDir目录)
由上面的目录结构可以看出,go的package路径实际上是从 ${GOPATH}/src 开始算的,上面的最标准的例子中,package路径即是从 projectDir 开始算的,中间的local目录也算package的路径,因此它是package 路径(但不是package名);而projectDir属于package的路径起始位置,也属于package路径(但不是package名);而 helloDir 即是package路径也是package名(但由于该package没有被外部引用,所以package路径与package名可以不相同,即 helloDir != main,其中main是package名)。真正的package名是由 .go 源文件声明的,如果该package会被其它文件/package所引用,则申明的package名必须与路径最后的目录名相同,不然编译通不过。强烈建议任何时候都保持package名与路径的最后一个目录名相同,不管该package是否被外部所引用,因为很难保证现在不被引用的package将来永远不会被引用。