Go最新的dep详解

该文翻译自https://medium.com/i-can-haz-downtime/dep-101-c85e8ab6ed45#.hbngswi0e

我很高兴在过去几个月和几个其他gopher开发的一个原型依赖管理工具,名为dep。

dep是去年开始由Peter Bourgon组织的项目的一部分。由于我参与开发了一个“godep”,Go的OG依赖管理工具(继承自Keith Rarick),因此加入了dep项目的团队。

除了我自己和Peter,团队的其他成员是Jessie Frazelle,Andrew Gerrand和Sam Boyer。 Andrew是Google Go team的一员。 Jessie在Google工作,并参与过大型Go项目,如Docker和Kubernetes。 Sam维护gps。

该团队发布了一系列我们工作过程中的进展信息。到目前为止,各种其他工具作者和相关方也以不同的方式参与这一项目。

起初

假设我们正在使用github.com/gorilla/mux编写一个Web应用程序。 这里是一些代码,让我们开始:

package main

import (
    "net/http"
    "os"

    "github.com/gorilla/mux"
)

func main() {
    r := mux.NewRouter()
    r.Handle("/", http.FileServer(http.Dir(".")))
    http.ListenAndServe(":"+os.Getenv("PORT"), r)
}

在现有项目上第一次使用dep时,需要运行dep init。

dep init将在GOPATH中已经包含github.com/gorilla/mux,manifest.json文件将包括它。我先运行如下命令:

go get -u github.com/gorilla/mux

所以在我的\$GOPATH中github.com/gorilla/mux的分支是master。如果我的\$GOPATH中的版本匹配Semver tag(例如:v1.2.3),那么将使用该tag的名称。

dep可以跨越架构和go版本。我们可以将github.com/gorilla/mux与旧版本的Go(<1.7.0)的github.com/gorilla/context包结合使用。当我最后运行

go get -u github.com/gorilla/mux

的时候,我运行的是Go 1.7.5,所以github.com/gorilla/context包不在我的\$GOPATH。因为可能是编译项目所需的依赖,它会包含在lock.json文件中。在这种场景下,如果从属项目有一个semver兼容的release tag,dep会选择最新的版本。在这种情况下是github.com/gorilla/context的v1.1。

因为github.com/gorilla/mux不包含manifest.json文件,dep不知道github.com/gorilla/mux目前是否能与github.com/gorilla/context@v1.1配合使用。dep一般使用在依赖的manifest.json文件中找到的约束。

dep init包括所有依赖关系(包括递归依赖)以及在lock.json文件中使用的确切版本。

对于示例应用程序,这将创建以下两个文件:
lock.json

{
    "memo": "d741a3bed21fe6cae9d67c523b0a343859882b2f246f2a293e2676cfacd5a2ce",
    "projects": [
        {
            "name": "github.com/gorilla/context",
            "version": "v1.1",
            "revision": "a85d2e53ba63bdea074dbbbb5983f0516974e87b",
            "packages": [
                "."
            ]
        },
        {
            "name": "github.com/gorilla/mux",
            "branch": "master",
            "revision": "392c28fe23e1c45ddba891b0320b3b5df220beea",
            "packages": [
                "."
            ]
        }
    ]
}

manifest.json

{
    "dependencies": {
        "github.com/gorilla/mux": {
            "branch": "master"
        }
    }
}

确保项目可以编译

在运行dep init之后,应该运行dep ensure以便将构建项目所需的软件包副本填充在vendor/目录。 这确保任何项目的依赖项都包括在lock文件和vendor目录中。 如果你想确保记录所有的依赖,运行dep ensure。

添加依赖

添加另一个依赖项,只需在代码中使用它。 当需要检查你的工作时,你需要运行dep ensure更新lock.json文件和vendor/。 这将锁定项目到每个依赖项的最新发布版本。

如果最新版本不合适呢?

如果需要指定版本,可以使用ensure命令的备用形式,如:dep ensure github.com/gorilla/mux@\\^1.3.0。该命令修改manifest.json文件,约束dep使用github.com/gorilla/mux的\\^v1.3.0版本,解析依赖关系树并更新vendor/中的依赖关系。在示例应用程序上,因为dep已经选择了最新的可用版本1.3.0。但是,以后的更新(dep ensure -update)将不再跟踪主分支,而是使用semver标记的版本≥1.3.0和<2.0.0。

dep主要使用Rust cargo类似的操作符来选择依赖的版本。这些包括\\^,~和=。还有一个更严格的,向前兼容的匹配比\\^使用~。例如,dep确保github.com/com/gorilla/mux@~1.2.0将匹配大于等于1.2.0和小于1.3.0任何版本。要锁定到特定版本,请使用=(e.x. dep ensure github.com/com/gorilla/mux@=1.2.0)。在未来,dep计划将\\^作为默认前缀。

保持更新

要保持项目的依赖关系最新使用dep ensure -update,它将所有依赖关系更新为由manifest.json中的约束所允许的最新版本,并忽略lock.json的内容。 将新版本写入vendor/,并在lock.json中更新相应的元数据。
在将来,可以用dep ensure -update 更新单个依赖关系。

Status

当缺少依赖项时,dep status会告诉您哪些软件包缺失。 例如,这里是dep status的输出:

$ dep status
PROJECT                 MISSING PACKAGES
github.com/boltdb/bolt  [github.com/boltdb/bolt]

如果项目的lock.json是最新的,dep status命令显示所有依赖项的列表,作为项目,并为每个:

  • 应用约束

  • 选版本

  • 所选修订版本

  • 最新版本或修订版本

  • 使用的软件包数量。
    将bolt添加到示例项目并运行dep后,确保更新lock.json和vendor/,dep status如下所示:

$ dep status
PROJECT                     CONSTRAINT  VERSION        REVISION  LATEST   PKGS USED
github.com/boltdb/bolt      *           v1.3.0         583e893   v1.3.0   1
github.com/gorilla/context  *           v1.1           a85d2e5   v1.1     1
github.com/gorilla/mux      ^1.3.0      v1.3.0         392c28f   v1.3.0   1
golang.org/x/sys            *           branch master  7a6e564   7a6e564  1

这两种模式可以在将来合并。

移除依赖

dep remove删除manifest.json,lock.json和vendor/中的依赖关系。 使用示例应用程序,此提交从应用程序中删除github.com/gorilla/mux的使用,下一个提交是dep remove github.com/gorilla/mux的结果。 因为github.com/gorilla/mux被删除,github.com/gorilla/context不再需要,也会被删除。 如果在运行dep remove时仍然使用依赖关系,则命令将失败。 可以使用-force强制从manifest.json中删除约束。 但是,由于依赖项仍在使用中,它仍然在lock.json中并复制到vendor/。

未来

dep仍然处于实验阶段,有许多问题需要解决和很多工作要做。 我希望这篇文章清楚地显示了一些如何使用工具的例子。 使用方式可能会随着时间的推移通过社区反馈和请求而改变。 如果你有一些空闲时间,并有兴趣参与一些Go工具开发,请现在开始。
谢谢阅读!