Como importo uma versão específica de um pacote usando go get?

109

vindo de um Nodeambiente que usei para instalar uma versão específica de uma lib do fornecedor na pasta do projeto ( node_modules), dizendo npmpara instalar essa versão dessa lib a partir do package.jsonou diretamente do console, assim:

$ npm install express@4.0.0

Então eu costumava importar essa versão desse pacote no meu projeto apenas com:

var express = require('express');

Agora, eu quero fazer a mesma coisa com go. Como eu posso fazer isso? É possível instalar uma versão específica de um pacote? Se sim, usando um centralizado $GOPATH, como posso importar uma versão em vez de outra?

Eu faria algo assim:

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

Mas aí, como faço a diferença na importação?

Wilk
fonte
4
Você não sabe, não go geté a ferramenta correta se você deseja esse comportamento. Você pode pesquisar soluções para o seu problema específico no Google.
Wessie de
1
Leia isto
kostix
stackoverflow.com/questions/30188499/… Isso também parece útil
Earonrails
Para Go 1.11 ou superior, consulte Módulos Go: stackoverflow.com/questions/53682247/…
Everton

Respostas:

46

O Go 1.11 terá um recurso chamado módulos go e você pode simplesmente adicionar uma dependência com uma versão. Siga esses passos:

go mod init .
go mod edit -require github.com/wilk/uuid@0.0.1` 
go get -v -t ./...   
go build
go install 

Aqui está mais informações sobre esse tópico - https://github.com/golang/go/wiki/Modules

Krish
fonte
4
como fazer isso com go get only? eu precisava instalar um binário global go para uma versão específica
James Tan
7
@JamesTan go get github.com/wilk/[email protected](com GO111MODULE=on)
Neil Conway
5
A questão era usar go get, não go mod.
Bernardo Loureiro
40

Realmente surpreso que ninguém tenha mencionado gopkg.in .

gopkg.iné um serviço que fornece um wrapper (redirecionamento) que permite expressar versões como repo urls, sem realmente criar repos. Por exemplo , gopkg.in/yaml.v1vs gopkg.in/yaml.v2, embora ambos vivam emhttps://github.com/go-yaml/yaml

Isso não é perfeito se o autor não está seguindo as práticas adequadas de controle de versão (incrementando o número da versão ao quebrar a compatibilidade com versões anteriores), mas funciona com branches e tags.

Steven Soroka
fonte
5
Eu gosto (e uso) gopkg, mas o controle de versão não funciona corretamente com subpacotes. Apenas algo para estar ciente.
Alec Thomas,
gopkg.in não foi totalmente testado em versões antigas do git, então não funciona corretamente com git <v1.9
BMW
Além disso, só funciona para as versões principais. É inutilizável para garantir compilações reproduzíveis.
CAFxX
26

Você pode usar git checkoutpara obter uma versão específica e construir seu programa usando esta versão.

Exemplo:

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
João parana
fonte
A solução seria então fazer o checkout e instalar
ptman 01 de
@ aliaksei-maniuk nos dê uma solução melhor. Use https://github.com/golang/dep
João Paraná
15

Glide é um gerenciamento de pacotes realmente elegante para Go, especialmente se você vem de Node's NPM ou Rust's cargo.

Ele se comporta de perto ao novo recurso de fornecedor de Godep no 1.6, mas é muito mais fácil. Suas dependências e versões são "bloqueadas" dentro do diretório projectdir / vendor sem depender do GOPATH.

Instale com cerveja (OS X)

$ brew install glide

Inicie o arquivo glide.yaml (semelhante ao package.json). Isso também pega os pacotes importados existentes em seu projeto do GOPATH e os copia para o diretório / fornecedor do projeto.

$ glide init

Obtenha novos pacotes

$ glide get vcs/namespace/package

Atualize e bloqueie as versões dos pacotes. Isso cria o arquivo glide.lock no diretório do projeto para bloquear as versões.

$ glide up

Tentei deslizar e estou feliz usando-o no meu projeto atual.

Torta 'Oh' Pah
fonte
1
Para completar, aqui está o site do glide: glide.sh E aqui o repo: github.com/Masterminds/glide
Michael Franzl
infelizmente o Glide não está mais "ativo", na página do github eles sugerem migrar para o gerenciamento de pacotes oficial (agora vá para módulos)
damoiser
13

Atualização 18-11-23 : Do Go 1.11 mod é um experimento oficial. Por favor, veja a resposta @krish.
Atualização 19-01-01 : Do Go 1.12 mod ainda é um experimento oficial. A partir do Go 1.13, o modo de módulo será o padrão para todo o desenvolvimento.
Atualização 19-10-17 : From Go 1.13 mod é o gerenciador de pacotes oficial.

https://blog.golang.org/using-go-modules

Resposta antiga:

Você pode definir a versão oficial pelo dep

dep ensure --add github.com/gorilla/websocket@1.2.0
Vitams
fonte
3
A questão era usar go get, não dep.
Bernardo Loureiro
9

depé o experimento oficial para gerenciamento de dependências para a linguagem Go. Requer Go 1.8 ou mais recente para compilar.

Para começar a gerenciar dependências usando dep, execute o seguinte comando no diretório raiz do seu projeto:

dep init

Após a execução, dois arquivos serão gerados: Gopkg.toml("manifesto"), Gopkg.locke os pacotes necessários serão baixados no vendordiretório.

Vamos supor que você tenha o projeto que usa o github.com/gorilla/websocketpacote. depirá gerar os seguintes arquivos:

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

Existem comandos que ajuda você a update / delete / etc pacotes, por favor encontrar mais informações sobre repo github oficial de dep(ferramenta de gerenciamento de dependência para Go).

Aliaksei Maniuk
fonte
7

Hoje você pode usar apenas go getpara isso. Você pode buscar sua dependência pela tag de versão, branch ou mesmo pelo commit.

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

mais detalhes aqui - Como apontar a dependência do módulo Go em go.mod para um commit mais recente em um repo?

Go gettambém instalará o binário, como diz na documentação -

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

(de https://golang.org/cmd/go/ )

homiak
fonte
4

go get é o gerenciador de pacotes Go. Funciona de forma completamente descentralizada e como a descoberta de pacotes ainda é possível sem um repositório central de hospedagem de pacotes.

Além de localizar e baixar pacotes, a outra grande função de um gerenciador de pacotes é lidar com várias versões do mesmo pacote. Go tem a abordagem mais minimalista e pragmática de qualquer gerenciador de pacotes. Não existem versões múltiplas de um pacote Go.

go get sempre puxa do HEAD do branch padrão no repositório. Sempre. Isso tem duas implicações importantes:

  1. Como autor do pacote, você deve aderir à filosofia HEAD estável. Seu branch padrão deve ser sempre a versão estável e lançada de seu pacote. Você deve trabalhar em branches de recursos e somente fundir quando estiver pronto para lançar.

  2. Novas versões principais de seu pacote devem ter seu próprio repositório. Simplificando, cada versão principal de seu pacote (seguindo a versão semântica) teria seu próprio repositório e, portanto, seu próprio caminho de importação.

    por exemplo, github.com/jpoehls/gophermail-v1 e github.com/jpoehls/gophermail-v2.

Como alguém que está criando um aplicativo em Go, a filosofia acima realmente não tem uma desvantagem. Cada caminho de importação é uma API estável. Não há números de versão com que se preocupar. Impressionante!

Para mais detalhes: http://zduck.com/2014/go-and-package-versioning/

faisal_kk
fonte
45
Suas afirmações sobre a funcionalidade das ferramentas go estão corretas, mas quase ninguém incorpora versões em seus nomes de repositório git, e muitas pessoas não tratam master / HEAD como uma API estável. Atualmente, tenho um pequeno serviço com cerca de oito dependências; apenas um tem um número de versão. A Amazon enviou uma alteração importante para github.com/aws/aws-sdk-go. go getO cache do significa que você não percebe por um tempo, a menos que tenha um servidor de compilação que o atualize com a versão mais recente todas as vezes. Existem gerenciadores de pacotes de terceiros, mas eles são quase sempre toscos.
dhasenan
19
@faisal_kk você deve estar vivendo em um mundo de sonho. No mundo REAL da maravilhosa comunidade de código aberto, todos estão aderindo à sua própria filosofia. Não existe tal coisa de lançamentos ramificados, estou feliz por termos tags.
28
Criar um repositório para cada versão? É uma loucura
deFreitas
8
Este é um comportamento fundamentalmente errado. O código-fonte NÃO é o mesmo que um pacote lançado, e você não pode incluir autores de pacotes para garantir compatibilidade com versões anteriores / posteriores. Não porque os desenvolvedores sejam incompetentes, mas porque isso é teoricamente impossível quando o número de dependências de pacote aumenta além de um. Go get está, portanto, destinado a seguir o mesmo caminho que bower, cuja principal falha era exatamente esta. O controle de versão semântica também não é forte o suficiente, somas de verificação binárias são realmente o único caminho a percorrer.
Gudlaugur Egilsson
5
"Não há números de versão com que se preocupar. Incrível!" Essa deve ser a declaração mais absurda de uma resposta SO. O controle de versão existe por uma razão. A falta de um gerenciador de pacotes de Go que tenha uma configuração embutida ou mecanismo orientado a comandos para versionamento de dependências, por exemplo, não significa que o versionamento seja um incômodo. Downvoting!
Harindaka
2

A abordagem que achei viável é o sistema de submódulos do git . Usando isso, você pode submódulo em uma determinada versão do código e a atualização / desatualização é explícita e registrada - nunca ao acaso.

A estrutura de pastas que usei com isso é:

+ myproject
++ src
+++ myproject
+++ github.com
++++ submoduled_project of some kind.
buckaroo1177125
fonte
Eu também uso essa abordagem. Basicamente, ele segue a mesma estrutura de pastas de go get, mas permite que você controle melhor a versão que está adquirindo.
Brad Peabody
a resposta não responde à pergunta com os critérios formulados (usando go get)
Baptiste Mille-Mathias
2

Existe um comando go edit -replace para anexar um commit específico (mesmo de outro repositório bifurcado) no topo da versão atual de um pacote. O que é legal sobre essa opção, é que você não precisa saber a pseudo versão exata de antemão, apenas o id de hash do commit .

Por exemplo, estou usando a versão estável do pacote "github.com/onsi/ginkgo v1.8.0".

Agora eu quero - sem modificar esta linha do pacote obrigatório em go.mod - adicionar um patch do meu fork, em cima da versão ginkgo:

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

Depois da primeira vez que você construir ou testar seu módulo, o GO tentará obter a nova versão e, em seguida, gerar a linha "substituir" com a pseudo versão correta. Por exemplo, no meu caso, ele adicionará na parte inferior de go.mod:

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

Noam Manos
fonte
2

Uma pequena folha de dicas sobre as consultas do módulo.

Para verificar todas as versões existentes: por exemplo go list -m -versions github.com/gorilla/mux

  1. Versão específica @ v1.2.8
  2. Compromisso específico @ c783230
  3. Commit específico @master
  4. Prefixo da versão @ v2
  5. Comparação @> = 2.1.5
  6. Último @latest

Por exemplo go get github.com/gorilla/[email protected]

Monkrus
fonte