若谷学院
互联网公司技术架构分享

Golang 项目依赖管理

Golang 项目依赖管理

golang官方提供了包管理工具go get,它将下载的第三方包放到GOPATH的src目录下。项目通常由很多来源不同的包构成,它们都从GOPATH或标准库中导入。

为了项目可以正常使用这些包,我们可能需要这么做:

  • 将依赖的包拷贝到项目源码路径下,重写代码中report的包名。
  • 将依赖的包拷贝到项目源码路径下,将项目路径加入到GOPATH。
  • 在文件中写入记录版本,然后将现有GOPATH的包更新为该版本。

虽然项目间会有所不同,但大方向上是这样的。

Vendor

Vendor是什么?

Go 1.5发布了一个新的发现包的方法,不需要在代码或编译器中做任何修改。如果项目中包含一个叫vendor的目录,go将会从这个目录搜索依赖的包,这些包会在标准库之前被找到。

Go 1.5开启这个功能需要修改环境变量 GO15VENDOREXPERIMENT=1, 1.6之后默认已开启。

比如导入了这些包

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"
)
...

我们看下vendor目录

$ 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,功能够用。但今天我们主要说说官方的dep,原生的在兼容上应该会越来越好,最近一些新的项目也在尝试使用dep。

Dep

dep is a prototype dependency management tool for Go. It requires Go 1.9 or newer to compile. dep is safe for production use.

Install

dep is the official experiment, but not yet the official tool.

在最新的1.1.10版本中仍然没加入,目前还是需要自己来安装

go get -u github.com/golang/dep/cmd/dep

Purpose

Dep is a tool for managing dependencies for Go projects

Usage: "dep [command]"

Commands:

  init     Set up a new Go project, or migrate an existing one
  status   Report the status of the project's dependencies
  ensure   Ensure a dependency is safely vendored in the project
  prune    Pruning is now performed automatically by dep ensure.
  version  Show the dep version information

Examples:
  dep init                               set up a new project
  dep ensure                             install the project's dependencies
  dep ensure -update                     update the locked versions of all dependencies
  dep ensure -add github.com/pkg/errors  add a dependency to the project

Use "dep help [command]" for more information about a command.

New project

接下来咱就结合项目看看具体的使用方法。在此之前我们需要先给项目设置根目录,一般情况都使用\$GOPATH/src

dep init

在项目下执行dep init

$ dep init
$ ls
Gopkg.toml Gopkg.lock vendor/

dep init有个-gopath选项,会优先从本地GOPATH导入所需要的包,能在一定程度上加快速度。

发现2个新文件,Gopkg.lock、Gopkg.toml,它们和vendor有什么关系?

Gopkg.toml是我们主要编辑的文件,它包含了dep的几种类型规则

  • Dependency rules: constraints、overrides 指定要依赖的版本以及从哪里获取
  • Package graph rules: required、ignored 指定要导入、排除的包
  • metadata: 用户可以自定义的key/value,dep会忽略这些配置。
  • prune: 设置哪些文件、目录是不需要的,它们会自动从vendor目录移除。

Dependency rules

gopkg.toml中的大多数规则声明来自[[constraint]][[override]]。它们设置的参数完全相同,但dep会用不同方式解释它们。

[[constraint]]
  # Required: the root import path of the project being constrained.
  name = "github.com/user/project"
  # Recommended: the version constraint to enforce for the project.
  # Note that only one of "branch", "version" or "revision" can be specified.
  version = "1.0.0"
  branch = "master"
  revision = "abc123"

  # Optional: an alternate location (URL or import path) for the project's source.
  source = "https://github.com/myfork/package.git"

  # Optional: metadata about the constraint or override that could be used by other independent systems
  [metadata]
  key1 = "value that convey data to other systems"
  system1-data = "value that is used by a system"
  system2-data = "value that is used by another system"

这里特别需要注意,”branch”, “version” or “revision” 只能写一个

Package graph rules

dep会解析代码中import语句,将这些导入的包最终形成一个图表。required、ignored决定导入或删除哪些包

如果项目依赖某个包,但report又没声明,可以使用required

metadata、prune一般用的少,大家感觉可以看下官方的介绍

dep ensure

dep ensure是dep最主要的命令,它确保整个项目是同步的。

dep基于report语句生成Gopkg.toml文件,通过ensure同步Gopkg.lock。并确保最终vendor目录下的内容就是我们想要的。

Adding a new dependency

$ dep ensure -add github.com/sumaig/glog

如果成功,它会更新Gopkg.lock文件和vendor目录,并选择最佳版本写入Gopkg.toml。但你也可能会遇到下面的错误:

"github.com/sumaig/glog" is not imported by your project, and has been temporarily added to Gopkg.lock and vendor/.
If you run "dep ensure" again before actually importing it, it will disappear from Gopkg.lock and vendor/.

这是因为我们没有在import声明这个包

Updating dependencies

更新指定包依赖

dep ensure -update github.com/sumaig/glog

更新所有依赖

dep ensure -update

遇到以下两种情况,我们也应该运行dep ensure确保项目是同步的

  • report中增加、减少包的声明
  • 修改了Gopkg.toml的任何规则
  • 这样的提示: Gopkg.toml and Gopkg.lock are out of sync.

Migrating to Dep

大多数项目直接运行dep init就可以完成迁移,如果之前用的是glide,dep会自动从glide.yml、glide.lock中读取项目依赖,这个也很方便。

原文出自:https://www.opsdev.cn/archives/

好烂呀没啥价值凑合看看还不错很精彩 (还没有人评分)
Loading...
本站文章来自互联网一线技术博客,若有侵权,请联系我们:若谷技术学院 » Golang 项目依赖管理
关注若谷技术,获得个性化即时架构文章推送

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

全球互联网技术架构,前沿架构参考

联系我们博客/网站内容提交