Come si importa una versione specifica di un pacchetto utilizzando go get?


109

provenendo da un Nodeambiente ho usato per installare una versione specifica di una lib del fornitore nella cartella del progetto ( node_modules) dicendo npmdi installare quella versione di quella lib dalla package.jsono anche direttamente dalla console, in questo modo:

$ npm install express@4.0.0

Quindi importavo quella versione di quel pacchetto nel mio progetto solo con:

var express = require('express');

Ora, voglio fare la stessa cosa con go. Come lo posso fare? È possibile installare una versione specifica di un pacchetto? In caso affermativo, utilizzando un sistema centralizzato $GOPATH, come posso importare una versione invece di un'altra?

Vorrei fare qualcosa di simile:

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

Ma allora come posso fare la differenza durante l'importazione?


4
Non lo fai, non go getè lo strumento corretto se vuoi questo comportamento. Puoi cercare su Google le soluzioni al tuo problema specifico.
Wessie

1
Leggi questo
kostix


Per Go 1.11 o versioni successive, vedi Go Modules: stackoverflow.com/questions/53682247/…
Everton

Risposte:


47

Go 1.11 avrà una funzionalità chiamata go modules e puoi semplicemente aggiungere una dipendenza con una versione. Segui questi passi:

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

Ecco maggiori informazioni su questo argomento: https://github.com/golang/go/wiki/Modules


4
come si fa con go get only? avevo bisogno di installare un binario go globale per una versione specifica
James Tan

7
@JamesTan go get github.com/wilk/uuid@0.0.1(con GO111MODULE=on)
Neil Conway

5
La domanda stava usando go get, no go mod.
Bernardo Loureiro

40

Davvero sorpreso nessuno ha menzionato gopkg.in .

gopkg.inè un servizio che fornisce un wrapper (reindirizzamento) che consente di esprimere le versioni come URL di repository, senza creare effettivamente repository. Ad esempio gopkg.in/yaml.v1vs gopkg.in/yaml.v2, anche se entrambi vivono ahttps://github.com/go-yaml/yaml

Questo non è perfetto se l'autore non segue le corrette pratiche di controllo delle versioni (incrementando il numero di versione quando si interrompe la compatibilità con le versioni precedenti), ma funziona con branch e tag.


5
Mi piace (e uso) gopkg, ma il controllo delle versioni non funziona correttamente con i sotto-pacchetti. Solo qualcosa di cui essere consapevoli.
Alec Thomas,

gopkg.in non è completamente testato nelle vecchie versioni di git, quindi non funziona correttamente con git <v1.9
BMW

Inoltre, funziona solo per le versioni principali. È inutilizzabile per garantire build riproducibili.
CAFxX

26

È possibile utilizzare git checkoutper ottenere una versione specifica e creare il programma utilizzando questa versione.

Esempio:

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

La soluzione sarebbe quindi git checkout e installazione
ptman

@ aliaksei-maniuk dacci una soluzione migliore. Usa https://github.com/golang/dep
João Paraná

15

Glide è una gestione dei pacchetti davvero elegante per Go, specialmente se provieni dal carico di Node o di Rust.

Si comporta in modo simile alla nuova funzionalità del fornitore di Godep nella versione 1.6 ma è molto più semplice. Le tue dipendenze e versioni sono "bloccate" nella directory projectdir / vendor senza fare affidamento su GOPATH.

Installa con brew (OS X)

$ brew install glide

Inizializza il file glide.yaml (simile a package.json). Questo cattura anche i pacchetti importati esistenti nel tuo progetto da GOPATH e li copia nella directory vendor / del progetto.

$ glide init

Ottieni nuovi pacchetti

$ glide get vcs/namespace/package

Aggiorna e blocca le versioni dei pacchetti. Questo crea il file glide.lock nella directory del progetto per bloccare le versioni.

$ glide up

Ho provato la planata e l'ho usata felicemente per il mio progetto attuale.


1
Per completezza, ecco il sito web di glide: glide.sh E qui il repo: github.com/Masterminds/glide
Michael Franzl

purtroppo Glide non è più "attivo", nella pagina github suggeriscono di migrare alla gestione ufficiale dei pacchetti (ora vai moduli)
damoiser

13

Aggiornamento 18-11-23 : dalla mod Go 1.11 è un esperimento ufficiale. Si prega di vedere la risposta di @krish.
Aggiornamento 19-01-01 : dalla mod Go 1.12 è ancora un esperimento ufficiale. A partire da Go 1.13, la modalità modulo sarà l'impostazione predefinita per tutto lo sviluppo.
Aggiornamento 19-10-17 : da Go 1.13 la mod è il gestore di pacchetti ufficiale.

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

Vecchia risposta:

È possibile impostare la versione da ufficiale dep

dep ensure --add github.com/gorilla/websocket@1.2.0

3
La domanda stava usando go get, no dep.
Bernardo Loureiro


9

depè l'esperimento ufficiale per la gestione delle dipendenze per Go language. Richiede Go 1.8 o più recente per la compilazione.

Per iniziare a gestire le dipendenze usando dep, esegui il seguente comando dalla directory principale del tuo progetto:

dep init

Dopo l'esecuzione verranno generati due file: Gopkg.toml("manifest") Gopkg.locke i pacchetti necessari verranno scaricati nella vendordirectory.

Supponiamo che tu abbia il progetto che usa github.com/gorilla/websocketpackage. depgenererà i seguenti file:

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

Ci sono comandi che ti aiutano ad aggiornare / eliminare i pacchetti / etc, per favore trova maggiori informazioni sul repository github ufficiale di dep(strumento di gestione delle dipendenze per Go).


7

Al giorno d'oggi puoi semplicemente usarlo go get. Puoi recuperare la tua dipendenza dal tag della versione, dal ramo o persino dal 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

maggiori dettagli qui - Come puntare la dipendenza del modulo Go in go.mod a un commit più recente in un repository?

Go getinstallerà anche il binario, come dice nella documentazione -

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

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


4

go get è il gestore di pacchetti Go. Funziona in modo completamente decentralizzato e la scoperta dei pacchetti è ancora possibile senza un repository di hosting del pacchetto centrale.

Oltre a individuare e scaricare i pacchetti, l'altro grande ruolo di un gestore di pacchetti è la gestione di più versioni dello stesso pacchetto. Go adotta l'approccio più minimale e pragmatico di qualsiasi gestore di pacchetti. Non esistono versioni multiple di un pacchetto Go.

go get estrae sempre dall'HEAD del ramo predefinito nel repository. Sempre. Ciò ha due importanti implicazioni:

  1. In qualità di autore di pacchetti, devi aderire alla filosofia HEAD stabile. Il tuo ramo predefinito deve sempre essere la versione stabile e rilasciata del tuo pacchetto. Devi lavorare nei rami delle funzionalità e unire solo quando sei pronto per il rilascio.

  2. Le nuove versioni principali del pacchetto devono avere il proprio repository. In parole povere, ogni versione principale del pacchetto (dopo il versionamento semantico) avrebbe il proprio repository e quindi il proprio percorso di importazione.

    ad es. github.com/jpoehls/gophermail-v1 e github.com/jpoehls/gophermail-v2.

Come qualcuno che crea un'applicazione in Go, la filosofia di cui sopra non ha davvero un aspetto negativo. Ogni percorso di importazione è un'API stabile. Non ci sono numeri di versione di cui preoccuparsi. Eccezionale!

Per maggiori dettagli: http://zduck.com/2014/go-and-package-versioning/


45
Le tue affermazioni sulla funzionalità degli strumenti go sono corrette, ma quasi nessuno incorpora versioni nei nomi dei propri repository git e molte persone non trattano master / HEAD come un'API stabile. Al momento ho un piccolo servizio con circa otto dipendenze; solo uno ha un numero di versione. Amazon ha apportato una modifica decisiva a github.com/aws/aws-sdk-go. go getLa memorizzazione nella cache significa che non te ne accorgi per un po 'a meno che tu non abbia un server di compilazione che ti aggiorna utilmente all'ultima versione ogni volta. Ci sono gestori di pacchetti di terze parti, ma sono per lo più rozzi.
dhasenan

19
@faisal_kk devi vivere in un mondo da sogno. Nel mondo REALE della meravigliosa comunità open source, ognuno aderisce alla propria filosofia. Non esiste una cosa del genere nei rilasci ramificati, sono contento che abbiamo i tag.

28
Creare un repository per ogni versione? È pazzesco
deFreitas

8
Questo è un comportamento fondamentalmente sbagliato. Il codice sorgente NON è lo stesso di un pacchetto rilasciato e non è possibile inserire autori di pacchetti per garantire la compatibilità con le versioni precedenti / successive. Non perché gli sviluppatori siano incompetenti, ma perché ciò è teoricamente impossibile quando il numero di dipendenze dei pacchetti aumenta oltre uno. Go get è quindi destinato ad andare allo stesso modo del pergolato, il cui difetto principale era esattamente lo stesso. Anche il versionamento semantico non è abbastanza potente, i checksum binari sono davvero l'unica strada da percorrere.
Gudlaugur Egilsson

5
"Non ci sono numeri di versione di cui preoccuparsi. Fantastico!" Questa deve essere l'affermazione più assurda mai vista in una risposta SO. Il controllo delle versioni esiste per un motivo. La mancanza di un gestore di pacchetti da parte di Go che abbia una configurazione incorporata o un meccanismo orientato ai comandi per il controllo delle versioni delle dipendenze per dire non implica che il controllo delle versioni sia un fastidio. Downvoting!
Harindaka

2

L'approccio che ho trovato praticabile è il sistema di sottomoduli di git . Usandolo puoi sottomodulare in una data versione del codice e l'aggiornamento / il downgrade è esplicito e registrato, mai a caso.

La struttura delle cartelle che ho preso con questo è:

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

Uso anche questo approccio. Essenzialmente segue la stessa struttura di cartelle di go get, ma ti consente di controllare meglio quale versione stai acquisendo.
Brad Peabody

la risposta non risponde alla domanda con i criteri posti (utilizzando go get)
Baptiste Mille-Mathias

2

Ha funzionato per me

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


2

C'è un comando go edit -replace per aggiungere un commit specifico (anche da un altro repository forkato) sopra la versione corrente di un pacchetto. La cosa interessante di questa opzione è che non è necessario conoscere in anticipo la pseudo versione esatta , solo l' id hash del commit .

Ad esempio, sto utilizzando la versione stabile del pacchetto "github.com/onsi/ginkgo v1.8.0".

Ora voglio - senza modificare questa riga del pacchetto richiesto in go.mod - aggiungere una patch dal mio fork, oltre alla versione ginkgo:

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

Dopo la prima volta che si crea o si prova il modulo, GO proverà a eseguire il pull della nuova versione, quindi genererà la riga "sostituisci" con la pseudo versione corretta. Ad esempio, nel mio caso, aggiungerà in fondo a go.mod:

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


2

Un piccolo cheat sheet sulle query del modulo.

Per controllare tutte le versioni esistenti: es go list -m -versions github.com/gorilla/mux

  1. Versione specifica @ v1.2.8
  2. Commit specifico @ c783230
  3. Commit specifico @master
  4. Prefisso versione @ v2
  5. Confronto @> = 2.1.5
  6. Ultimi @latest

Per esempio go get github.com/gorilla/mux@v1.7.4

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.