www.zhblog.net

vendor


在只有一个项目的情况下,GOPATH非常合情合理而且简单,如果有多个项目,各个项目的源码也可以放在同一个GOPATH之中,有着各自的包结构,使用着来自GOPATH的非标准包,此时整个GOPATH目录就是一个巨大的 repository,具称 Google 内部就是这样的场景,才会有GOPATH这样的设计,Go 社区中也有着「如果必须切换GOPATH,大概有哪些地方不对了」的说法。

问题在于,这并不是社区或其他公司中使用 Go 的方式,如果个别项目有个别的包,比较单纯的做法是各个项目有个专用的GOPATH,想要开发哪个项目,就切换至该项目使用的GOPATH,然而很快地,如果有项目依赖在这些个别项目上呢?将它们组织为巨大的 repository 是个做法,或者是令GOPATH=prj1:prj2:prj3,prjx 是指向各项目源码的路径,也就是说GOPATH会是一大串路径结合后的产物。

在上述的设定中,维持了一个GOPATH不用切换,新项目可以加入至GOPATH最前头,go get的第三方包会下载到最前面的路径中,然而,若需要 prj2 也在开发中,若 prj2 需要新的第三方包时,go get却会下载到新项目之中;在各自不同的情境中,无论怎么调整GOPATH的顺序,总是会有各自不同的问题发生。

另一方面,GOPATH本身不涉及包来源的版本问题,因此,若项目依赖的 repository 被修改了,日后构造项目就会受到影响,对依赖于Github之类来源,而且第三方包本身非常活跃的项目来说,重新构造项目时无法有稳定的结果,这显然是个大问题。

例如在〈Go 包管理〉中看过的例子,使用go get github.com/JustinSDK/goexample,然后编写底下的程序:

package main

import "github.com/JustinSDK/goexample"

func main() {
    goexample.Hi()
    goexample.Hello()
}

这简单的程序被发布为一个范例了,某年某月的某一天,我修改了 goexample 的内容,让HiHello显示中文并发布到 Github 上的文件库,有位读者,依旧照着〈Go 包管理〉中的说明进行操作,然而看到的不是英文,而是中文的招呼。

为了避免这个问题,通常会将下载的文件库复制出来,例如放到 deps 中:

project
    └─src
        ├─deps
        │  └─src
        │      └─github.com
        │          └─JustinSDK
        │              └─goexample
        │                      .gitignore
        │                      hello.go
        │                      hi.go
        │                      LICENSE
        │                      README.md
        │
        └─main
                main.go

问题是放到 deps 的文件库该怎么用呢?其中一个方式是修改import

package main

import "deps/src/github.com/JustinSDK/goexample"

func main() {
    goexample.Hi()
    goexample.Hello()
}

另一个方式是透过工具修改GOPATH自动包含 deps 目录,这类的概念主要成为了godep等工具早期在管理 Go 包时的思考出发点。

Go 在 1.5 时实验性地加入了 vendor,需要透过GO15VENDOREXPERIMENT="1"来启用,1.6 默认GO15VENDOREXPERIMENT="1",1.7 拿掉GO15VENDOREXPERIMENT环境变量,使得vendor成为正式的内置特性。

简单来说,如果你的包中有个 vendor 文件夹,例如:

project
    └─src
        └─main
            │  main.go
            │
            └─vender
                └─github.com
                    └─JustinSDK
                        └─goexample
                                .gitignore
                                hello.go
                                hi.go
                                LICENSE
                                README.md

对于import "github.com/JustinSDK/goexample"来说,寻找依赖包的顺序会变成 vendor -> GOROOT 的 src -> GOPATH 的 src。

在 vendor 推出后,godep也改使用 vendor了,而glide等工具,也都基于 vendor 了。


展开阅读全文

评论

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 心情