Die Verwaltung von Abhängigkeiten ist Go war schon immer problematisch. Es gibt verschiedene Strategien und Tools, die uns bei der Verwaltung unserer Codebasis und Abhängigkeiten helfen, aber keine einzige Lösung war wirklich zielführend.
GOPATH-Abhängigkeitsverwaltung
Die GOPAH-Abhängigkeitsverwaltung ist die Art und Weise, wie wir in Go traditionell Abhängigkeiten hinzufügen. Wir laden mit dem Befehl 'go get' einen Schnappschuss des Quellcodes in den 'GOPATH' und kompilieren unser Hauptprogramm. Wenn wir eine Bibliothek mit 'go get -u' aktualisieren, könnte unsere Codebasis zusammenbrechen. Ein Grund dafür könnte eine transitive Abhängigkeit sein, die mit einer Bibliothek, von der unsere Anwendung abhängt, inkompatibel ist.
Zum Beispiel hängt unser Programm von 'google/uuid' ab, aber das AWS SDK für Go hat auch eine Abhängigkeit von 'google/uuid', aber eine andere Version. Wenn diese Bibliotheken inkompatibel sind, ist unsere Codebasis kaputt. Dieses Problem kann auftreten, wenn unser Programm zuvor funktionierte, aber nach einem Upgrade einer Bibliothek ist alles kaputt. Da wir einen einzigen 'GOPATH' haben, gibt es keine einfache Möglichkeit, dieses Problem zu beheben.
Alternativen Ansätze
Alternative Ansätze zur Verwaltung von Abhängigkeiten wurden ausprobiert, z.B. goven, godep, glide, gb, govendor, dep und das Vendor-Verzeichnis. Leider sind die Ergebnisse der Strategien unterschiedlich und, was noch schlimmer ist, sie spalten die Go-Gemeinschaft in verschiedene Strategien und Tools zur Verwaltung von Abhängigkeiten.
Go Module
Die von Go bereitgestellten Go-Module (GM) versuchen, das Go-Abhängigkeitsmanagement ein für alle Mal zu lösen. GM führt neue Konzepte wie ein Modul, die go.mod-Datei, die semantische Versionsauswahl und einen neuen Satz von Befehlen ein, die dem Go-Tool hinzugefügt wurden.
Arbeiten außerhalb von GOPATH
Die tiefgreifendste Änderung bei GM ist, dass Module außerhalb des GOPATH existieren können. Mit GM können Sie Ihre Module überall im Dateisystem ablegen. Auf meinem System bewahre ich alle meine Projekte im Verzeichnis '~/projects' auf. Mit GM kann ich ein Projektverzeichnis anlegen und ein Go-Modul in diesem Verzeichnis erstellen. Mit GM lädt Go alle Abhängigkeiten herunter, kompiliert, testet und installiert das Modul als statische Binärdatei.
Hallo Welt Modul
Lassen Sie uns eine Hello World-Anwendung erstellen:
$ pwd
cd ~/projects
$ mkdir hello-gm
$ cd hello-gm
# initialize a new module
$ go mod init github.com/dnvriend/hello-gm
go: creating new go.mod: module github.com/dnvriend/hello-gm
$ ls
go.mod
Der Befehl go mod init hat eine einzige Datei namens go.mod im Stammverzeichnis erstellt, die eine einzige Zeile enthält:
module github.com/dnvriend/hello-gm
Da wir eine go.mod Datei im Stammverzeichnis unseres Projekts haben, haben wir unsere erste GM mit dem Namen 'github.com/dnvriend/hello-gm' erstellt.
Implementierung von Main
Lassen Sie uns eine Datei main.go im Stammverzeichnis des Projektordners erstellen.
package main
import (
"fmt"
"rsc.io/quote"
)
func main() {
fmt.Println(quote.Hello())
}
Lassen Sie es laufen:
$ go run main.go
go: finding rsc.io/quote v1.5.2
go: downloading rsc.io/quote v1.5.2
go: finding rsc.io/sampler v1.3.0
go: finding golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
go: downloading rsc.io/sampler v1.3.0
go: downloading golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
Hello, world.
Go hat die Abhängigkeiten heruntergeladen und das Beispiel ausgeführt. Lassen Sie uns untersuchen, was passiert ist.
go.mod Datei
Schauen wir uns an, was in dem Verzeichnis passiert ist:
.
├── go.mod
├── go.sum
└── main.go
Wir haben die folgenden Dateien:
- main.go: enthält das Hallo-Welt-Beispiel
- go.mod: definiert das Modul und die Abhängigkeiten und enthält genügend Informationen für reproduzierbare Builds
- go.sum: eine neue Datei. Die go.sum enthält Prüfsummen und dient nur zur Modulvalidierung
helloworld go.mod Datei:
module github.com/dnvriend/hello-gm
require rsc.io/quote v1.5.2
Go hat automatisch eine Abhängigkeit zum Modul rsc.io/quote hinzugefügt. Go untersuchte die go.mod-Datei von quote und entdeckte weitere Abhängigkeiten.
rsc.io/quote go.mod Datei:
module rsc.io/quote
require (
rsc.io/quote/v3 v3.0.0
rsc.io/sampler v1.3.0
)
Laden Sie alle Abhängigkeiten in das Modul-Cache-Verzeichnis herunter, aktualisieren Sie die Datei go.mod von 'hello world' und führen Sie das Beispiel aus. Natürlich können wir die Datei go.mod auch manuell bearbeiten und dort eine Version einfügen, die wir benötigen.
Auflistung aller Abhängigkeiten
Wir können eine Liste aller Abhängigkeiten erhalten, indem wir eingeben:
$ go list -m all
github.com/dnvriend/hello-gm
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
rsc.io/quote v1.5.2
rsc.io/sampler v1.3.0
Module Cache-Verzeichnis
Das Cache-Verzeichnis für GM ist $GOPATH/pkg/mod. Wenn Sie das Verzeichnis entfernen, muss Go alle Abhängigkeiten erneut herunterladen und erstellen.
Hallo Eimer
Lassen Sie uns eine neue App namens 'hello-buckets' erstellen, die alle S3-Buckets in unserem Konto anzeigt.
$ cd ~/projects
$ mkdir hello-buckets
$ cd hello-buckets
$ go mod init com.github/dnvriend/hello-buckets
Fügen wir die notwendigen Abhängigkeiten hinzu:
$ go get github.com/aws/aws-sdk-go
go: finding github.com/aws/aws-sdk-go v1.15.82
go: downloading github.com/aws/aws-sdk-go v1.15.82
$ go get github.com/olekukonko/tablewriter
go: finding github.com/mattn/go-runewidth v0.0.3
go: downloading github.com/mattn/go-runewidth v0.0.3
Schauen wir uns das Modul hello-buckets an:
go.mod:
$ cat go.mod
module com.github/dnvriend/hello-buckets
require (
github.com/aws/aws-sdk-go v1.15.82 // indirect
github.com/mattn/go-runewidth v0.0.3 // indirect
github.com/olekukonko/tablewriter v0.0.1 // indirect
)
Implementierung von Main
Lassen Sie uns eine Datei main.go im Stammverzeichnis des Projektordners erstellen.
package main
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/olekukonko/tablewriter"
"os"
)
func main() {
sess, _ := session.NewSession()
svc := s3.New(sess, aws.NewConfig().WithRegion("eu-west-1"))
request := s3.ListBucketsInput{}
resp, _ := svc.ListBuckets(&request)
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"Name", "CreationDate"})
for _, bucket := range resp.Buckets {
date := *bucket.CreationDate
table.Append([]string{*bucket.Name, date.String()})
}
table.Render()
}
Lassen Sie uns das Beispiel ausführen:
$ go run main.go
+-------------------------------------------------+-------------------------------+
| NAME | CREATIONDATE |
+-------------------------------------------------+-------------------------------+
| aws-athena-query-results-612483924670-eu-west-1 | 2018-10-01 20:02:38 +0000 UTC |
| aws-athena-query-results-eu-west-1-612483924670 | 2018-10-01 19:58:47 +0000 UTC |
| cf-templates-1vt4xsan6d30f-eu-west-1 | 2018-10-24 10:12:26 +0000 UTC |
| dennisvriend | 2018-08-15 19:47:35 +0000 UTC |
| dennisvriend.com | 2018-06-04 18:56:29 +0000 UTC |
| dennisvriend.io | 2018-06-27 17:15:10 +0000 UTC |
| dennisvriend.nl | 2018-06-05 09:30:11 +0000 UTC |
| dnvriend-awslabs | 2018-08-15 17:12:37 +0000 UTC |
| dnvriend-data | 2018-07-08 09:58:10 +0000 UTC |
| dnvriend.com | 2018-06-05 09:30:24 +0000 UTC |
| dnvriend.nl | 2018-06-05 09:30:33 +0000 UTC |
| elasticbeanstalk-eu-west-1-612483924670 | 2018-07-02 06:32:18 +0000 UTC |
| www.dennisvriend.com | 2018-09-15 17:46:49 +0000 UTC |
| www.dnvriend.nl | 2018-09-15 17:47:05 +0000 UTC |
+-------------------------------------------------+-------------------------------+
Fazit
Go Module macht die Verwaltung von Go-Abhängigkeiten wirklich einfach. Die Datei go.mod erinnert mich an andere Abhängigkeitssysteme wie build.sbt des Scala Build Tool (SBT), wo Sie 'libraryDependencies' nach Name und Version angeben. Go v1.11 ist in das Modulsystem integriert. Die Befehle 'go get' und 'go mod' erkennen, wenn es in einem Modulverzeichnis arbeitet und laden abhängige Module herunter. Mit Go Modules kann ich auch außerhalb des GOPATH arbeiten, so dass ich Module in Projektverzeichnissen erstellen kann, wie mit 'hello-gm' und 'hello-buckets'.
Verfasst von
Dennis Vriend
Unsere Ideen
Weitere Blogs
Contact




