Golang 包依赖管理

3,094 阅读2分钟
原文链接: addops.cn

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