Problem
Go 程序通常由很多来源不同的包构成,每个包都从GOPATH或标准库中导入。为了项目可以正常使用这些包,我们可能需要这么做:
- 将依赖的包copy到项目源码路径下,重写代码中report的包名。
- 将依赖的包copy到项目源码路径下,将项目路径加入到GOPATH。
- 在文件中写入存储库版本,然后将现有GOPATH的包更新为该版本。
虽然项目间会有略微不同,但大方向上是这样的。
这里最大的问题是每个项目依赖的包都不同,还有些其他问题,例如:
- 大多数人都不喜欢修改report路径或将依赖包放到他们的仓库中
- 需要每个项目有不同的GOPATH
Solution
Go 1.5发布了一个新的发现包的方法,不需要在代码或编译器中做任何修改。如果项目中包含一个叫vendor的目录,go将会从这个目录搜索依赖的包,这些包会在标准库之前被找到。
Go 1.5 开启这个功能需要修改环境变量 GO15VENDOREXPERIMENT=1, 1.6之后默认已开启。
Example
$ cat main.go
package main
import (
"bytes"
"flag"
"io"
"io/ioutil"
"log"
"net/http"
"net/url"
"os"
"path"
"path/filepath"
"strings"
"sync"
"time"
"github.com/andybalholm/cascadia"
"github.com/tdewolff/parse/css"
"golang.org/x/net/html"
)
...
看下目录结构
$ tree
.
├── css_test.go
├── main.go
└── vendor
├── github.com
│ ├── andybalholm
│ │ └── cascadia
│ │ ├── LICENSE
│ │ ├── parser.go
│ │ ├── README.md
│ │ └── selector.go
│ └── tdewolff
│ ├── buffer
│ │ ├── buffer.go
│ │ ├── lexer.go
│ │ ├── LICENSE.md
│ │ ├── reader.go
│ │ ├── README.md
│ │ ├── shifter.go
│ │ └── writer.go
│ └── parse
│ ├── common.go
│ ├── css
│ │ ├── hash.go
│ │ ├── lex.go
│ │ ├── parse.go
│ │ ├── README.md
│ │ └── util.go
│ ├── LICENSE.md
│ ├── README.md
│ └── util.go
├── golang.org
│ └── x
│ └── net
│ └── html
│ ├── atom
│ │ ├── atom.go
│ │ ├── gen.go
│ │ └── table.go
│ ├── const.go
│ ├── doc.go
│ ├── doctype.go
│ ├── entity.go
│ ├── escape.go
│ ├── foreign.go
│ ├── node.go
│ ├── parse.go
│ ├── render.go
│ └── token.go
How to use the vendor folder
使用方式有很多种,大多是第三方软件,常用的有godep、glide。官方也有dep,但目前使用起来比较复杂且不稳定。建议使用glide
Glide
Glide是一个支持vendor特性的工具,使用简单、功能强大。
- 初始化
在项目下执行 glide init
过程中会出现类似情况,按提示操作即可
$glide init
[INFO] Generating a YAML configuration file and guessing the dependencies
[INFO] Attempting to import from other package managers (use --skip-import to skip)
[INFO] Scanning code to look for dependencies
[INFO] --> Found reference to github.com/Masterminds/semver
[INFO] --> Found reference to github.com/Masterminds/vcs
[INFO] --> Found reference to github.com/codegangsta/cli
[INFO] --> Found reference to gopkg.in/yaml.v2
[INFO] Writing configuration file (glide.yaml)
[INFO] Would you like Glide to help you find ways to improve your glide.yaml configuration?
[INFO] If you want to revisit this step you can use the config-wizard command at any time.
[INFO] Yes (Y) or No (N)?
n
[INFO] You can now edit the glide.yaml file. Consider:
[INFO] --> Using versions and ranges. See https://glide.sh/docs/versions/
[INFO] --> Adding additional metadata. See https://glide.sh/docs/glide.yaml/
[INFO] --> Running the config-wizard command to improve the versions in your configuration
- 编辑glide.yaml
初始化后会在项目下创建一个glide.yaml文件,记录了项目中依赖包的详细信息。
package: github.com/Masterminds/glide
homepage: https://masterminds.github.io/glide
license: MIT
owners:
- name: Matt Butcher
email: technosophos@gmail.com
homepage: http://technosophos.com
- name: Matt Farina
email: matt@mattfarina.com
homepage: https://www.mattfarina.com
ignore:
- appengine
excludeDirs:
- node_modules
import:
- package: gopkg.in/yaml.v2
- package: github.com/Masterminds/vcs
version: ^1.2.0
repo: git@github.com:Masterminds/vcs
vcs: git
- package: github.com/codegangsta/cli
version: f89effe81c1ece9c5b0fda359ebd9cf65f169a51
- package: github.com/Masterminds/semver
version: ^1.0.0
testImport:
- package: github.com/arschles/assert
- 安装依赖包
glide install
这个命令会把项目中所有依赖的包都安装到vendor目录下。
- 新增依赖包
当项目中需要新增其他依赖包,可以这样做 glide get github.com/foo/bar