Wie importiere ich eine bestimmte Version eines Pakets mit go get?

107

NodeIch komme aus einer Umgebung, in der ich eine bestimmte Version einer Herstellerbibliothek im Projektordner ( node_modules) npminstalliert habe, indem ich angewiesen habe , diese Version dieser Bibliothek von der package.jsonoder sogar direkt von der Konsole aus zu installieren , wie folgt:

$ npm install express@4.0.0

Dann habe ich diese Version dieses Pakets in mein Projekt importiert, nur mit:

var express = require('express');

Jetzt möchte ich das Gleiche tun go. Wie kann ich das machen? Ist es möglich, eine bestimmte Version eines Pakets zu installieren? Wenn ja, $GOPATHwie kann ich mithilfe einer zentralen Version eine Version anstelle einer anderen importieren?

Ich würde so etwas machen:

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

Aber wie kann ich dann beim Import einen Unterschied machen?

Wilk
quelle
4
Sie nicht, go getist nicht das richtige Werkzeug, wenn Sie dieses Verhalten wollen. Sie können nach Lösungen für Ihr spezifisches Problem suchen.
Wessie
1
Lesen Sie dies
kostix
stackoverflow.com/questions/30188499/… Das sieht auch hilfreich aus
earlonrails
Für Go 1.11 oder höher siehe Go-Module: stackoverflow.com/questions/53682247/…
Everton

Antworten:

45

Go 1.11 wird eine Funktion namens go modules haben und Sie können einfach eine Abhängigkeit mit einer Version hinzufügen. Folge diesen Schritten:

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

Hier finden Sie weitere Informationen zu diesem Thema - https://github.com/golang/go/wiki/Modules

krish
quelle
4
wie macht man das nur mit go get? Ich musste eine globale Go-Binärdatei für eine bestimmte Version installieren
James Tan
6
@ JamesTan go get github.com/wilk/[email protected](mit GO111MODULE=on)
Neil Conway
5
Die Frage benutzte go getnicht go mod.
Bernardo Loureiro
40

Wirklich überrascht, dass niemand gopkg.in erwähnt hat .

gopkg.inist ein Dienst, der einen Wrapper (Redirect) bereitstellt, mit dem Sie Versionen als Repo-URLs ausdrücken können, ohne tatsächlich Repos zu erstellen. ZB gopkg.in/yaml.v1vs gopkg.in/yaml.v2, obwohl beide bei lebenhttps://github.com/go-yaml/yaml

Dies ist nicht perfekt, wenn der Autor nicht die richtigen Versionsverfahren befolgt (indem er die Versionsnummer erhöht, wenn die Abwärtskompatibilität unterbrochen wird), aber es funktioniert mit Zweigen und Tags.

Steven Soroka
quelle
5
Ich mag (und benutze) gopkg, aber die Versionierung funktioniert mit Unterpaketen nicht richtig . Nur etwas zu beachten.
Alec Thomas
gopkg.in ist in git alten Versionen nicht vollständig getestet, daher funktioniert es nicht richtig mit git <v1.9
BMW
Außerdem funktioniert es nur für Hauptversionen. Es ist unbrauchbar, reproduzierbare Builds zu garantieren.
CAFxX
26

git checkoutMit dieser Version können Sie eine bestimmte Version abrufen und Ihr Programm erstellen.

Beispiel:

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 Paraná
quelle
Die Lösung wäre dann, git checkout zu gehen und zu installieren
ptman
@ aliaksei-maniuk geben uns eine bessere Lösung. Verwenden Sie https://github.com/golang/dep
João Paraná
15

Glide ist ein wirklich elegantes Paketmanagement für Go, besonders wenn Sie von Node's npm oder Rust's Fracht kommen.

Es verhält sich ähnlich wie die neue Herstellerfunktion von Godep in 1.6, ist jedoch viel einfacher. Ihre Abhängigkeiten und Versionen sind in Ihrem Projektverzeichnis / Herstellerverzeichnis "gesperrt", ohne auf GOPATH angewiesen zu sein.

Mit Brew installieren (OS X)

$ brew install glide

Initialisieren Sie die Datei glide.yaml (ähnlich wie package.json). Dadurch werden auch die vorhandenen importierten Pakete in Ihrem Projekt von GOPATH abgerufen und dann in den Anbieter / das Verzeichnis des Projekts kopiert.

$ glide init

Holen Sie sich neue Pakete

$ glide get vcs/namespace/package

Aktualisieren und sperren Sie die Versionen der Pakete. Dadurch wird die Datei glide.lock in Ihrem Projektverzeichnis erstellt, um die Versionen zu sperren.

$ glide up

Ich habe versucht zu gleiten und benutze es gerne für mein aktuelles Projekt.

Pie 'Oh' Pah
quelle
1
Der Vollständigkeit halber hier die Website für glide: glide.sh Und hier das Repo: github.com/Masterminds/glide
Michael Franzl
Leider ist Glide nicht mehr "aktiv", auf der Github-Seite schlagen sie vor, zur offiziellen Paketverwaltung zu migrieren (jetzt gehen Module)
Damoiser
13

Update 18-11-23 : From Go 1.11 Mod ist offizielles Experiment. Bitte siehe @krish Antwort.
Update 19-01-01 : From Go 1.12 Mod ist noch offizielles Experiment. Ab Go 1.13 ist der Modulmodus die Standardeinstellung für alle Entwicklungen.
Update 19-10-17 : From Go 1.13 Mod ist offizieller Paketmanager.

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

Alte Antwort:

Sie können die Version durch offizielle Abteilung einstellen

dep ensure --add github.com/gorilla/websocket@1.2.0
Vitame
quelle
3
Die Frage benutzte go getnicht dep.
Bernardo Loureiro
9

depist das offizielle Experiment zum Abhängigkeitsmanagement für die Go-Sprache. Zum Kompilieren ist Go 1.8 oder neuer erforderlich.

depFühren Sie den folgenden Befehl aus dem Stammverzeichnis Ihres Projekts aus, um mit der Verwaltung von Abhängigkeiten zu beginnen :

dep init

Nach der Ausführung werden zwei Dateien generiert: Gopkg.toml("Manifest") Gopkg.lockund die erforderlichen Pakete werden in das vendorVerzeichnis heruntergeladen .

Nehmen wir an, Sie haben das Projekt, das das github.com/gorilla/websocketPaket verwendet. depgeneriert folgende Dateien:

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

Es gibt Befehle, die Ihnen beim Aktualisieren / Löschen / etc-Paketen helfen. Weitere Informationen zum offiziellen Github-Repo von dep(Abhängigkeitsmanagement-Tool für Go).

Aliaksei Maniuk
quelle
7

Heutzutage kann man es einfach dafür verwenden go get. Sie können Ihre Abhängigkeit über das Versions-Tag, den Zweig oder sogar das Commit abrufen.

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

Weitere Details hier - Wie kann die Go-Modulabhängigkeit in go.mod auf ein aktuelles Commit in einem Repo hingewiesen werden?

Go getwird auch installieren die binäre, wie es in der Dokumentation sagt -

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

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

Homiak
quelle
4

go get ist der Go-Paketmanager. Es funktioniert vollständig dezentral und wie die Paketerkennung ohne ein zentrales Paket-Hosting-Repository noch möglich ist.

Neben dem Auffinden und Herunterladen von Paketen besteht die andere große Rolle eines Paketmanagers darin, mehrere Versionen desselben Pakets zu verarbeiten. Go verfolgt den minimalsten und pragmatischsten Ansatz eines Paketmanagers. Es gibt nicht mehrere Versionen eines Go-Pakets.

go get zieht immer aus dem HEAD des Standardzweigs im Repository. Immer. Dies hat zwei wichtige Auswirkungen:

  1. Als Paketautor müssen Sie sich an die stabile HEAD-Philosophie halten. Ihr Standardzweig muss immer die stabile, freigegebene Version Ihres Pakets sein. Sie müssen in Feature-Zweigen arbeiten und erst dann zusammenführen, wenn Sie zur Freigabe bereit sind.

  2. Neue Hauptversionen Ihres Pakets müssen über ein eigenes Repository verfügen. Einfach ausgedrückt, hätte jede Hauptversion Ihres Pakets (nach der semantischen Versionierung) ein eigenes Repository und damit einen eigenen Importpfad.

    zB github.com/jpoehls/gophermail-v1 und github.com/jpoehls/gophermail-v2.

Als jemand, der eine Anwendung in Go erstellt, hat die obige Philosophie wirklich keinen Nachteil. Jeder Importpfad ist eine stabile API. Es gibt keine Versionsnummern, über die Sie sich Sorgen machen müssen. Genial!

Für weitere Informationen: http://zduck.com/2014/go-and-package-versioning/

faisal_kk
quelle
45
Ihre Aussagen zur Funktionalität von go-Tools sind korrekt, aber fast niemand nimmt Versionen in seine Git-Repository-Namen auf, und viele Leute behandeln master / HEAD nicht als stabile API. Ich habe derzeit einen kleinen Dienst mit ungefähr acht Abhängigkeiten; Nur einer hat eine Versionsnummer. Amazon hat eine bahnbrechende Änderung an github.com/aws/aws-sdk-go vorgenommen. go getDas Caching bedeutet, dass Sie es eine Weile nicht bemerken, es sei denn, Sie haben einen Build-Server, der Sie jedes Mal auf die neueste Version aktualisiert. Es gibt Paketmanager von Drittanbietern, die jedoch größtenteils grob sind.
Dhasenan
19
@faisal_kk du musst in einer traumwelt leben. In der REALEN Welt der wunderbaren Open-Source-Community hält jeder an seiner eigenen Philosophie fest. Es gibt keine verzweigten Releases. Ich bin froh, dass wir Tags haben.
28
Für jede Version ein Repository erstellen? Es ist verrückt
deFreitas
8
Dies ist grundsätzlich falsches Verhalten. Der Quellcode ist NICHT mit einem freigegebenen Paket identisch, und Sie können keine Paketautoren aktivieren, um die Abwärts- / Vorwärtskompatibilität sicherzustellen. Nicht weil Entwickler inkompetent sind, sondern weil dies theoretisch unmöglich ist, wenn die Anzahl der Paketabhängigkeiten über eins steigt. Go get ist daher dazu bestimmt, den gleichen Weg zu gehen wie Bower, dessen Hauptfehler genau der gleiche war. Die semantische Versionierung ist auch nicht stark genug, binäre Prüfsummen sind wirklich der einzige Weg.
Gudlaugur Egilsson
5
"Es gibt keine Versionsnummern, über die man sich Sorgen machen müsste. Genial!" Das muss die absurdeste Aussage in einer SO-Antwort sein, die es je gab. Die Versionierung gibt es aus einem Grund. Das Fehlen eines Paketmanagers von Go, der über eine integrierte Konfiguration oder einen befehlsorientierten Mechanismus für die Versionierung von Abhängigkeiten verfügt, bedeutet nicht, dass die Versionierung ein Ärgernis darstellt. Downvoting!
Harindaka
2

Der Ansatz, den ich für praktikabel befunden habe, ist das Submodul-System von git . Damit können Sie eine bestimmte Version des Codes submodulieren und das Upgrade / Downgrade ist explizit und aufgezeichnet - niemals zufällig.

Die Ordnerstruktur, die ich damit genommen habe, ist:

+ myproject
++ src
+++ myproject
+++ github.com
++++ submoduled_project of some kind.
buckaroo1177125
quelle
Ich benutze diesen Ansatz auch. Im Wesentlichen folgt es der gleichen Ordnerstruktur wie go get, ermöglicht Ihnen jedoch eine bessere Kontrolle darüber, welche Version Sie erwerben.
Brad Peabody
Die Antwort beantwortet die Frage nicht mit den gestellten Kriterien (unter Verwendung go get)
Baptiste Mille-Mathias
2

Es gibt einen Befehl go edit -replace, mit dem ein bestimmtes Commit (auch aus einem anderen gegabelten Repository) an die aktuelle Version eines Pakets angehängt werden kann . Das Coole an dieser Option ist, dass Sie nicht vorher die genaue Pseudoversion kennen müssen, sondern nur die Commit-Hash-ID .

Zum Beispiel verwende ich die stabile Version des Pakets "github.com/onsi/ginkgo v1.8.0".

Jetzt möchte ich - ohne diese Zeile des erforderlichen Pakets in go.mod zu ändern - einen Patch von meiner Gabel über die Ginkgo-Version anhängen:

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

Nach dem ersten Erstellen oder Testen Ihres Moduls versucht GO, die neue Version abzurufen und anschließend die Zeile "Ersetzen" mit der richtigen Pseudoversion zu generieren. In meinem Fall wird beispielsweise unten in go.mod Folgendes hinzugefügt:

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

Noam Manos
quelle
2

Ein kleiner Spickzettel zu Modulabfragen.

So überprüfen Sie alle vorhandenen Versionen: z go list -m -versions github.com/gorilla/mux

  1. Spezifische Version @ v1.2.8
  2. Spezifisches Commit @ c783230
  3. Spezifisches Commit @master
  4. Versionspräfix @ v2
  5. Vergleich @> = 2.1.5
  6. Neueste @latest

Z.B go get github.com/gorilla/[email protected]

monkrus
quelle