如何使用go get导入特定版本的软件包?

时间:2014-07-20 21:28:02

标签: go package package-managers

来自Node环境,我曾经通过告诉node_modules安装该版本的lib来安装特定版本的供应商lib到项目文件夹(npmpackage.json甚至直接来自控制台,如下所示:

$ npm install express@4.0.0

然后我曾经在我的项目中导入该软件包的那个版本:

var express = require('express');

现在,我想对go做同样的事情。我怎样才能做到这一点? 是否可以安装特定版本的软件包?如果是这样,使用集中式$GOPATH,如何导入一个版本而不是另一个版本?

我会做这样的事情:

$ go get github.com/wilk/uuid@0.0.1
$ go get github.com/wilk/uuid@0.0.2

但是,如何在导入过程中有所作为呢?

13 个答案:

答案 0 :(得分:38)

真的很惊讶没有人提到gopkg.in

gopkg.in是一种提供包装器(重定向)的服务,它允许您将版本表示为repo URL,而不实际创建repos。例如。 gopkg.in/yaml.v1 vs gopkg.in/yaml.v2,即使他们都住在https://github.com/go-yaml/yaml

如果作者没有遵循正确的版本控制实践(通过在向后兼容性时增加版本号),这并不完美,但它确实适用于分支和标记。

答案 1 :(得分:21)

您可以使用git checkout获取特定版本并使用此版本构建程序。

示例:

export GOPATH=~/
go get github.com/whateveruser/whateverrepo
cd ~/src/github.com/whateveruser/whateverrepo
git tag -l
# supose tag v0.0.2 is correct version
git checkout tags/v0.0.2
go run whateverpackage/main.go

答案 2 :(得分:20)

Go 1.11将具有一个称为go modules的功能,您可以简单地在版本中添加依赖项。

步骤

  1. go mod init .
  2. go mod edit -require github.com/wilk/uuid@0.0.1

有关该主题的更多信息: https://github.com/golang/go/wiki/Modules

答案 3 :(得分:13)

对于Go来说,

Glide 是一个非常优雅的包管理,特别是如果你来自Node的npm或Rust的货物。

它与1.6中Godep的新供应商功能密切相关,但更容易。您的依赖项和版本在projectdir / vendor目录中“锁定”,而不依赖于GOPATH。

使用brew安装(OS X)

$ brew install glide

初始化glide.yaml文件(类似于package.json)。这也会从GOPATH中获取项目中现有的导入包,然后复制到项目的vendor /目录中。

$ glide init

获取新包

$ glide get vcs/namespace/package

更新并锁定包的版本。这会在项目目录中创建glide.lock文件以锁定版本。

$ glide up

我尝试滑行,并乐意将它用于我当前的项目。

答案 4 :(得分:10)

您可以按官方dep

设置版本
dep ensure --add github.com/gorilla/websocket@1.2.0

更新18-11-23:来自Go 1.11 mod是官方实验。请参阅@krish答案。

答案 5 :(得分:9)

从Go 1.5开始,"vendor experiment"可帮助您管理依赖关系。从Go 1.6开始,这不再是一个实验。还有some other options on the Go wiki.

编辑:正如this answer中提到的gopkg.in是固定1.5之前的github-depdencies的好选择。

答案 6 :(得分:8)

dep是Go语言依赖管理的官方实验。它需要Go 1.8或更新版本才能编译。

要使用dep开始管理依赖项,请从项目的根目录运行以下命令:

dep init

执行后将生成两个文件:Gopkg.toml(“manifest”),Gopkg.lock,必要的包将被下载到vendor目录中。

假设您拥有使用github.com/gorilla/websocket包的项目。 official github repo将生成以下文件:

<强> Gopkg.toml

# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
#   name = "github.com/user/project"
#   version = "1.0.0"
#
# [[constraint]]
#   name = "github.com/user/project2"
#   branch = "dev"
#   source = "github.com/myfork/project2"
#
# [[override]]
#  name = "github.com/x/y"
#  version = "2.4.0"


[[constraint]]
  name = "github.com/gorilla/websocket"
  version = "1.2.0"

<强> Gopkg.lock

# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.


[[projects]]
  name = "github.com/gorilla/websocket"
  packages = ["."]
  revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b"
  version = "v1.2.0"

[solve-meta]
  analyzer-name = "dep"
  analyzer-version = 1
  inputs-digest = "941e8dbe52e16e8a7dff4068b7ba53ae69a5748b29fbf2bcb5df3a063ac52261"
  solver-name = "gps-cdcl"
  solver-version = 1

有一些命令可以帮助您更新/删除/ etc包,请在dep Runtime Error "13": Type Mismatch(Go的依赖管理工具)上找到更多信息。

答案 7 :(得分:7)

go get 是Go包管理器。它以完全分散的方式工作,如果没有中央软件包托管存储库,它仍然可以实现软件包发现。

除了查找和下载软件包之外,软件包管理器的另一个重要角色是处理同一软件包的多个版本。 Go采用任何包管理器最简单实用的方法。没有多个版本的Go包。

go get 始终从存储库中默认分支的HEAD中提取。总是。这有两个重要的含义:

  1. 作为包装作者,您必须遵守稳定的HEAD理念。您的默认分支必须始终是包的稳定版本。您必须在功能分支中工作,并且只有在准备发布时才合并。

  2. 您的软件包的新主要版本必须拥有自己的存储库。简而言之,您的软件包的每个主要版本(在语义版本控制之后)将拥有自己的存储库,从而拥有自己的导入路径。

    e.g。 github.com/jpoehls/gophermail-v1和github.com/jpoehls/gophermail-v2。

  3. 作为在Go中构建应用程序的人,上述哲学确实没有缺点。每个导入路径都是一个稳定的API。没有版本号需要担心。真棒!

    有关详情:http://zduck.com/2014/go-and-package-versioning/

答案 8 :(得分:4)

我发现可行的方法是git's submodule system。使用它可以在给定版本的代码中进行子模块,并且升级/降级是明确的并且被记录 - 从不随意。

我采用的文件夹结构是:

+ myproject
++ src
+++ myproject
+++ github.com
++++ submoduled_project of some kind.

答案 9 :(得分:3)

有关模块查询的速查表。

要检查所有现有版本,例如go list -m -versions github.com/gorilla/mux

  1. 特定版本 @ v1.2.8
  2. 特定提交 @ c783230
  3. 特定提交 @master
  4. 版本前缀 @ v2
  5. 比较 @> = 2.1.5
  6. 最新 @最新

例如go get github.com/gorilla/mux@v1.7.4

答案 10 :(得分:1)

对我有用

GO111MODULE=on go get -u github.com/segmentio/aws-okta@v0.22.1

答案 11 :(得分:1)

如今,您只能使用go get。您可以通过版本标记,分支甚至提交来获取依赖关系。

go get github.com/someone/some_module@master
go get github.com/someone/some_module@v1.1.0
go get github.com/someone/some_module@commit_hash

更多详细信息-How to point Go module dependency in go.mod to a latest commit in a repo?

Go get也将安装该二进制文件,如文档中所述-

Get downloads the packages named by the import paths, along with their dependencies. It then installs the named packages, like 'go install'.

(来自https://golang.org/cmd/go/

答案 12 :(得分:1)

有一个go edit -replace命令可将特定的提交(甚至来自另一个分叉的存储库)附加在当前版本的软件包之上。 此选项最酷的地方是,您无需事先知道确切的pseudo version,只需提交哈希ID

例如,我使用的是软件包“ github.com/onsi/ginkgo v1.8.0”的稳定版本。

现在,我想要-不修改go.mod中的必需软件包这一行-在银杏版本的顶部,从我的叉子上添加一个补丁:

$ GO111MODULE="on"  go mod edit -replace=github.com/onsi/ginkgo=github.com/manosnoam/ginkgo@d6423c2

在第一次构建或测试模块后,GO将尝试提取新版本,然后使用正确的伪版本生成“替换”行。例如,在我的情况下,它将添加在go.mod的底部:

  

替换github.com/onsi/ginkgo => github.com/manosnoam/ginkgo v0.0.0-20190902135631-1995eead7451