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