Hallo alle zusammen. Im Vorfeld des Beginns des Golang-Entwicklerkurses haben wir eine weitere interessante Übersetzung für Sie vorbereitet.
Module sind eine Möglichkeit, mit Abhängigkeiten in Go umzugehen. Zunächst als Experiment vorgestellt, sollen die Module als neuer Standard für die Verwaltung von Paketen ab Version 1.13 ins Feld eingeführt werden.Ich finde dieses Thema ungewöhnlich genug für Anfänger aus anderen Sprachen. Deshalb habe ich beschlossen, hier einige Gedanken und Tipps zu sammeln, um anderen wie mir zu helfen, sich ein Bild von der Paketverwaltung in Go zu machen. Wir beginnen mit einer allgemeinen Einführung und gehen dann zu den weniger offensichtlichen Aspekten über, einschließlich der Verwendung des Herstellerordners, der Verwendung von Modulen mit Docker in der Entwicklung, Werkzeugabhängigkeiten usw.Wenn Sie bereits mit Go-Modulen vertraut sind und das Wiki kennenWie Ihr Handrücken wird dieser Artikel für Sie wahrscheinlich nicht sehr hilfreich sein. Im Übrigen können jedoch mehrere Stunden Versuch und Irrtum eingespart werden.Wenn Sie unterwegs sind, springen Sie hinein und genießen Sie die Fahrt.
Schnellstart
Wenn die Versionskontrolle bereits in Ihr Projekt integriert ist, können Sie sie einfach ausführengo mod init
Oder geben Sie den Pfad zum Modul manuell an. Dies ist so etwas wie ein Name, eine URL und ein Importpfad für Ihr Paket:go mod init github.com/you/hello
Dadurch wird eine Datei erstellt go.mod
, in der auch die Projektanforderungen und das Lochit in Abhängigkeit von der richtigen Version definiert werden (als Analogie für Sie ist es wie package.json
und package-lock.json
in einer einzigen Datei zusammengefasst):module github.com/you/hello
go 1.12
Ausführen go get
, um Ihrem Projekt eine neue Abhängigkeit hinzuzufügen:Beachten Sie, dass Sie mit go get zwar keinen Versionsbereich angeben können, hier jedoch keine bestimmte Version, sondern eine Mindestversion definieren. Wie wir später sehen werden, gibt es eine Möglichkeit, Abhängigkeiten entsprechend dem Semver ordnungsgemäß zu aktualisieren.# use Git tags
go get github.com/go-chi/chi@v4.0.1
# or Git branch name
go get github.com/go-chi/chi@master
# or Git commit hash
go get github.com/go-chi/chi@08c92af
Jetzt ist unsere Datei go.mod
wie folgt:module github.com/you/hello
go 1.12
require github.com/go-chi/chi v4.0.2+incompatible
Das Suffix wird +incompatible
allen Paketen hinzugefügt, die noch nicht für Go-Module konfiguriert sind oder deren Versionskontrollregeln verletzen.Da wir dieses Paket nirgendwo in unserem Projekt importiert haben, wurde es als markiert // indirect
. Wir können dies mit dem folgenden Befehl aufräumen:go mod tidy
Abhängig vom aktuellen Status Ihres Repositorys wird entweder ein nicht verwendetes Modul oder ein Kommentar gelöscht // indirect
.Wenn eine Abhängigkeit für sich genommen keine hat go.mod
(z. B. ist sie noch nicht für Module konfiguriert), werden alle ihre Abhängigkeiten in die übergeordnete Datei geschrieben go.mod
(optional wird Ihre Datei go.mod)
zusammen mit einem Kommentar // indirect
angezeigt, um anzuzeigen, dass sie nicht direkt importiert werden In Ihremglobalen Plan besteht das Ziel go mod tidy
auch darin, Abhängigkeiten hinzuzufügen, die für andere Kombinationen von Betriebssystemen, Architekturen und Build-Tags erforderlich sind. Führen Sie diese vor jeder Version aus.Stellen Sie außerdem sicher, dass nach dem Hinzufügen der Abhängigkeit eine Datei erstellt wirdgo.sum
. Sie könnten denken, dass dies eine Sperrdatei ist. Tatsächlich go.mod
bietet es jedoch bereits genügend Informationen für 100% reproduzierbare Builds. Die Datei go.sum
wird zu Überprüfungszwecken erstellt: Sie enthält die erwarteten kryptografischen Prüfsummen des Inhalts einzelner Versionen des Moduls.Zum Teil, weil es sich go.sum
nicht um eine Sperrdatei handelt, werden die schriftlichen Prüfsummen für die Modulversion gespeichert, auch wenn Sie dieses Modul nicht mehr verwenden. Auf diese Weise können Sie die Prüfsummen überprüfen, wenn Sie sie später wieder verwenden, was zusätzliche Sicherheit bietet.
Mkcert ist gerade auf die Module migriert (mit Hersteller / aus Gründen der Abwärtskompatibilität) und alles verlief reibungslos.
Https://github.com/FiloSottile/mkcert/commit/26ac5f35395fb9cba3805faf1a5a04d260271291
$ GO111MODULE=on go1.11rc1 mod init
$ GO111MODULE=on go1.11rc1 mod vendor
$ git add go.mod go.sum vendor
$ git rm Gopkg.lock Gopkg.toml Makefile

FAQ: Soll ich mich go.sum
in Git verpflichten?
A: Auf jeden Fall ja. Damit müssen die Eigentümer Ihrer Quellen anderen GitHub-Repositorys und Eigentümern von benutzerdefinierten Importpfaden nicht vertrauen. Schon auf dem Weg zu uns, etwas Besseres, aber im Moment ist dies das gleiche Modell wie die Hashes in den Sperrdateien.
Die go build
und Befehle go test
werden alle fehlenden Abhängigkeiten automatisch laden, obwohl Sie dies explizit mit Hilfe tun können go mod download
pre-bevölkern lokalen Caches , die für CI nützlich sein kann.Standardmäßig werden alle unsere Pakete aus allen Projekten in das Verzeichnis geladen $GOPATH/pkg/mod
. Wir werden dies später genauer besprechen.Aktualisieren von Paketversionen
Sie können go get -u
entweder verwenden go get -u=patch
, um Abhängigkeiten auf die neueste Nebenversion bzw. den neuesten Patch zu aktualisieren.Sie können jedoch nicht auf solche Hauptversionen aktualisieren. Der in Go-Modulen enthaltene Code muss technisch den folgenden Regeln entsprechen:- Match Semver (Beispiel-Tag VCS v1.2.3).
- Wenn das Modul Version v2 oder höher ist, sollte die Hauptversion des Moduls sowohl
/vN
am Ende des in der Datei verwendeten Modulpfads go.mod
als auch im Paketimportpfad enthalten sein:
import "github.com/you/hello/v2"
Anscheinend geschieht dies, damit verschiedene Versionen von Paketen in eine Assembly importiert werden können (siehe Problem mit der Diamantabhängigkeit ).Kurz gesagt, Go erwartet von Ihnen, dass Sie bei der Einführung von Hauptversionen sehr vorsichtig sind.Importierte Module ersetzen
Sie können das erforderliche Modul für Ihre eigene Verzweigung oder sogar den lokalen Pfad zur Datei mithilfe der folgenden Anweisung angeben replace
:go mod edit -replace github.com/go-chi/chi=./packages/chi
Ergebnis:module github.com/you/hello
go 1.12
require github.com/go-chi/chi v4.0.2+incompatible
replace github.com/go-chi/chi => ./packages/chi
Sie können die Zeile manuell löschen oder ausführen:go mod edit -dropreplace github.com/go-chi/chi
Projektabhängigkeitsmanagement
In der Vergangenheit wurde der gesamte Go-Code in einem riesigen Mono-Repository gespeichert, da Google auf diese Weise seine Codebasis organisiert. Dies wirkt sich auf das Sprachdesign aus.Go-Module weichen von diesem Ansatz ab. Sie müssen nicht mehr alle Ihre Projekte behalten $GOPATH
.Technisch gesehen sind jedoch alle heruntergeladenen Abhängigkeiten weiterhin vorhanden $GOPATH/pkg/mod
. Wenn Sie Docker-Container für die lokale Entwicklung verwenden, kann dies ein Problem sein, da Abhängigkeiten außerhalb des Projekts gespeichert werden. Standardmäßig sind sie in Ihrer IDE einfach nicht sichtbar.
Dies ist normalerweise kein Problem für andere Sprachen, aber dies ist das, was ich zum ersten Mal bei der Arbeit mit der Go-Codebasis festgestellt habe.Glücklicherweise gibt es mehrere (undokumentierte) Möglichkeiten, um dieses Problem zu lösen.Option 1. Installieren Sie GOPATH in Ihrem Projektverzeichnis.
Auf den ersten Blick mag dies nicht intuitiv erscheinen, aber wenn Sie Go aus einem Container ausführen, können Sie GOPATH überschreiben, sodass es auf das Projektverzeichnis verweist, sodass auf Pakete vom Host aus zugegriffen werden kann:version: '3.7'
services:
app:
command: tail -f /dev/null
image: golang:1.12.6-stretch
environment:
# - /code/.go/pkg/mod
- GOPATH=/code/.go
ports:
- 8000:8000
volumes:
- ./:/code:cached
working_dir: /code
Beliebte IDEs sollten in der Lage sein, GOPATH auf Projektebene (Arbeitsbereich) zu installieren:
Der einzige Nachteil dieses Ansatzes ist die mangelnde Interaktion mit der Go-Laufzeit auf dem Host-Computer. Sie müssen alle Go-Befehle im Container ausführen.Option 2: Verkauf Ihrer Abhängigkeiten
Eine andere Möglichkeit besteht darin, die Abhängigkeiten Ihres Projekts in einen Ordner zu kopieren vendor
:go mod vendor
Es sollte sofort beachtet werden: Wir erlauben Go NICHT, Materialien direkt in den Lieferantenordner hochzuladen. Dies ist mit Modulen nicht möglich. Wir kopieren einfach bereits heruntergeladene Pakete.Wenn Sie Ihre Abhängigkeiten wie im obigen Beispiel lösen, dann löschen $GOPATH/pkg/mod
und dann versuchen, Ihrem Projekt mehrere neue Abhängigkeiten hinzuzufügen, wird Folgendes angezeigt :- Go erstellt den Download-Cache für alle Softwarepakete neu
$GOPATH/pkg/mod/cache
. - Alle geladenen Module werden kopiert
$GOPATH/pkg/mod
. - Schließlich kopiert Go diese Module in einen
vendor
Ordner und löscht Beispiele, Tests und einige andere Dateien, von denen Sie nicht direkt abhängig sind.
Darüber hinaus fehlen in diesem neu erstellten Herstellerordner viele Dinge:
Eine typische Docker Compose-Datei sieht folgendermaßen aus (beachten Sie die Datenträgerbindungen):version: '3.7'
services:
app:
command: tail -f /dev/null
image: golang:1.12.6-stretch
ports:
- 8000:8000
volumes:
# go,
- modules:/go/pkg/mod/cache
- ./:/code:cached
working_dir: /code
volumes:
modules:
driver: local
Bitte beachten Sie, dass ich diesen Herstellerordner im Versionskontrollsystem NICHT komisch mache oder ihn nicht in der Produktion verwenden werde. Dies ist ein streng lokales Entwicklungsskript, das normalerweise in einigen anderen Sprachen verfügbar ist.Wenn ich jedoch Kommentare von einigen Go-Betreuern und einige Angebote im Zusammenhang mit Teilverkäufen (?) Lies, habe ich den Eindruck, dass diese Funktion ursprünglich nicht für diesen Benutzerfall gedacht war.Einer der Kommentatoren von reddit hat mir dabei geholfen, etwas Licht ins Dunkel zu bringen:Normalerweise bieten die Benutzer ihre Abhängigkeiten aus Gründen wie dem Wunsch nach engen Assemblys ohne Zugriff auf das Netzwerk sowie einer Kopie vorgefertigter Abhängigkeiten im Falle eines Github-Fehlers oder des Verschwindens des Repositorys und der Möglichkeit einer einfacheren Prüfung von Abhängigkeitsänderungen mithilfe von Standard-VCS-Tools usw. an. .Ja, es sieht nicht wie etwas aus der Tatsache , dass ich interessiert sein könnte.Gemäß dem Befehl Go können Sie den Verkauf einfach aktivieren, indem Sie eine Umgebungsvariable festlegen GOFLAGS=-mod=vendor
. Ich empfehle dies nicht. Die Verwendung von Flags wird einfach unterbrochen, go get
ohne dass Ihr täglicher Workflow weitere Vorteile bietet:
Der einzige Ort, an dem Sie den Verkauf aktivieren müssen, ist Ihre IDE:
Nach einigem Ausprobieren habe ich das folgende Verfahren zum Hinzufügen von Lieferantenabhängigkeiten in diesem Ansatz entwickelt.Schritt 1. Anforderung
Sie können eine Abhängigkeit verlangen mit go get
:go get github.com/rs/zerolog@v1.14.3
Schritt 2. Importieren
Importieren Sie es dann irgendwo in Ihren Code:import (
_ "github.com/rs/zerolog"
)
Schritt 3. Verkauf
Öffnen Sie abschließend Ihre Abhängigkeiten erneut:go mod vendor
Es steht ein Vorschlag aus , dem Go-Mod-Anbieter zu erlauben, bestimmte Modulvorlagen zu akzeptieren, die möglicherweise einige der mit diesem Workflow verbundenen Probleme lösen (oder auch nicht).go mod vendor
erfordert bereits automatisch verpasste Importe, daher ist Schritt 1 in diesem Workflow optional (wenn Sie keine Versionsbeschränkungen angeben möchten). Ohne Schritt 2 wird das heruntergeladene Paket jedoch nicht abgerufen.Dieser Ansatz funktioniert besser mit dem Hostsystem, ist jedoch ziemlich verwirrend, wenn es darum geht, Ihre Abhängigkeiten zu bearbeiten.
Persönlich denke ich, dass die Neudefinition von GOPATH ein sauberer Ansatz ist, da die Funktionalität nicht beeinträchtigt wird go get
. Trotzdem wollte ich beide Strategien zeigen, da der Herstellerordner möglicherweise Personen aus anderen Sprachen wie PHP, Ruby, Javascript usw. besser bekannt ist. Wie Sie dem in diesem Artikel beschriebenen Betrug entnehmen können, ist dies der Fall keine besonders gute Wahl für Go.Werkzeugabhängigkeiten
Möglicherweise müssen wir einige Go-basierte Tools installieren, die nicht importiert, sondern als Teil der Projektentwicklungsumgebung verwendet werden. Ein einfaches Beispiel für ein solches Tool ist CompileDaemon , mit dem Sie Ihren Code auf Änderungen überwachen und Ihre Anwendung neu starten können.Der offiziell empfohlene Ansatz besteht darin, eine tools.go
Datei (der Name spielt keine Rolle) mit folgendem Inhalt hinzuzufügen :
package tools
import (
_ "github.com/githubnemo/CompileDaemon"
)
- Die Einschränkung
// +build tools
verhindert, dass Ihre regulären Baugruppen Ihr Werkzeug tatsächlich importieren. - Mit dem Importausdruck können go-Befehle Versionsinformationen Ihrer Tools genau in
go.mod
Ihre Moduldatei schreiben .
Das ist also alles. Ich hoffe, Sie werden nicht so verwirrt sein wie zu Beginn meiner Verwendung von Go-Modulen. Weitere Informationen finden Sie im Go Modules-Wiki .
Steig auf den Kurs.