Los geht's Befehlszeilenprogramme mit Golang

Überblick

The Go Language ist eine aufregende neue Sprache, die aus gutem Grund sehr beliebt ist. In diesem Lernprogramm erfahren Sie, wie Sie mit Go Befehlszeilenprogramme schreiben. Das Beispielprogramm heißt multi-git und ermöglicht Ihnen die Ausführung von git-Befehlen in mehreren Repositorys gleichzeitig.

Schnelleinstieg

Go ist eine Open-Source-C-ähnliche Sprache, die bei Google von einigen der ursprünglichen C- und Unix-Hacker erstellt wurde, die durch ihre Abneigung gegen C ++ motiviert waren. Dies zeigt sich in Gos Design, das mehrere unorthodoxe Entscheidungen getroffen hat, wie z. B. Implementierungsvererbung, Vorlagen und Ausnahmen. Go ist einfach, zuverlässig und effizient. Das auffälligste Merkmal ist die explizite Unterstützung der gleichzeitigen Programmierung über sogenannte Goroutines und Kanäle.

Bevor Sie mit der Analyse des Beispielprogramms beginnen, befolgen Sie die offiziellen Anleitungen, um sich auf die Go-Entwicklung vorzubereiten.

Go ist eine unglaublich mächtige Programmiersprache. Sie lernen alles vom Schreiben einfacher Hilfsprogramme bis zum Erstellen von skalierbaren, flexiblen Webservern in unserem gesamten Kurs.

Das Multi-Git-Programm

Das Multi-Git-Programm ist ein einfaches, aber nützliches Go-Programm. Wenn Sie in einem Team arbeiten, in dem die Codebase auf mehrere Git-Repositorys aufgeteilt ist, müssen Sie häufig Änderungen in mehreren Repositorys vornehmen. Dies ist ein Problem, da git kein Konzept für mehrere Repositorys hat. Alles dreht sich um ein einzelnes Repository. 

Dies wird besonders störend, wenn Sie Äste verwenden. Wenn Sie an einem Feature arbeiten, das drei Repositorys berührt, müssen Sie in jedem dieser Repositorys einen Feature-Zweig erstellen und daran denken, alle Objekte gleichzeitig auszuchecken, zu ziehen, zu drücken und zusammenzuführen. Das ist nicht trivial. Multi-git verwaltet eine Reihe von Repositorys und ermöglicht die gleichzeitige Bearbeitung der gesamten Gruppe. Beachten Sie, dass Sie für die aktuelle Version von Multi-Git die Verzweigungen einzeln erstellen müssen. Ich kann diese Funktion jedoch zu einem späteren Zeitpunkt hinzufügen.

Wenn Sie die Implementierung von Multi-Git erkunden, werden Sie viel über das Schreiben von Befehlszeilenprogrammen in Go lernen.

Pakete und Importe

Go-Programme sind in Paketen organisiert. Das Multi-Git-Programm besteht aus einer einzigen Datei namens main.go. Oben in der Datei wird der Paketname 'main' angegeben, gefolgt von einer Liste der Importe. Die Importe sind andere Pakete, die von Multi-Git verwendet werden.

Paket-Hauptimport ("flag" "fmt" "log" "os" "Zeichenfolgen" "os / exec")

Das fmt-Paket wird beispielsweise für formatierte E / A verwendet, ähnlich wie bei printf und scanf von C. Go unterstützt die Installation von Paketen aus verschiedenen Quellen über die geh holen Befehl. Wenn Sie Pakete installieren, landen sie in einem Namespace unter $ GOPATH Umgebungsvariable. Sie können Pakete aus verschiedenen Quellen wie GitHub, Bitbucket, Google Code, Launchpad und sogar IBM DevOps-Services über verschiedene gängige Versionskontrollformate wie git, subversion, mercurial und bazaar installieren.

Kommandozeilenargumente

Befehlszeilenargumente sind eine der häufigsten Formen der Eingabe von Programmen. Sie sind einfach zu bedienen, ermöglichen es Ihnen, das Programm in einer Zeile auszuführen und zu konfigurieren, und bieten eine hervorragende Unterstützung für die Analyse in vielen Sprachen. Go nennt sie Befehlszeilen "Flags" und enthält das Flag-Paket zum Angeben und Analysieren von Befehlszeilenargumenten (oder Flags).. 

Normalerweise analysieren Sie Befehlszeilenargumente am Anfang Ihres Programms, und Multi-git folgt dieser Konvention. Der Einstiegspunkt ist der Main() Funktion. Die ersten beiden Zeilen definieren zwei Flags, die als "command" und "ignoreErrors" bezeichnet werden. Jedes Flag hat einen Namen, einen Datentyp, einen Standardwert und eine Hilfefolge. Das flag.Parse () call parst die tatsächliche Befehlszeile, die an das Programm übergeben wurde, und füllt die definierten Flags auf.

func main () command: = flag.String ("command", "", "The git command") ignoreErrors: = flag.Bool ("ignore-errors", false, "Lauf nach Fehler, falls wahr",) .Parse ()

Es ist auch möglich, undefinierte Argumente über die flag.Args () Funktion. Flags stehen also für vordefinierte Argumente und "Argumente" sind unverarbeitete Argumente. Die nicht verarbeiteten Argumente sind 0-basiert indiziert.

Umgebungsvariablen

Eine andere übliche Form der Programmkonfiguration sind Umgebungsvariablen. Wenn Sie Umgebungsvariablen verwenden, können Sie dasselbe Programm mehrmals in derselben Umgebung ausführen, und alle Läufe verwenden die gleichen Umgebungsvariablen. 

Multi-Git verwendet zwei Umgebungsvariablen: "MG_ROOT" und "MG_REPOS". Multi-git dient zum Verwalten einer Gruppe von Git-Repositorys mit einem gemeinsamen übergeordneten Verzeichnis. Das ist "MG_ROOT". Die Repository-Namen werden in "MG_REPOS" als durch Kommas getrennte Zeichenfolge angegeben. Um den Wert einer Umgebungsvariablen zu lesen, können Sie die verwenden os.Getenv () Funktion.

 // Verwaltete Repos von Umgebungsvariablen erhalten root: = os.Getenv ("MG_ROOT") if root [len (root) - 1]! = '/' Root + = "/" repo_names: = strings.Split (os .Getenv ("MG_REPOS"), ",")

Überprüfen der Repository-Liste

Nachdem nun das Stammverzeichnis und die Namen aller Repositorys gefunden wurden, überprüft Multi-git, dass jedes Repository unter root vorhanden ist und dass es sich wirklich um ein Git-Repository handelt. Die Prüfung ist so einfach wie die Suche nach einem .git-Unterverzeichnis für jedes Repository-Verzeichnis.

Zunächst wird ein Array von Strings mit dem Namen "Repos" definiert. Dann durchläuft es alle Repo-Namen und erstellt einen Repository-Pfad durch Verketten des Stammverzeichnisses und des Repo-Namens. Wenn die [os.Stat ()] () Aufruf schlägt für das .git-Unterverzeichnis fehl, protokolliert den Fehler und wird beendet. Andernfalls wird der Repository-Pfad an das Repos-Array angehängt.

 var repos [] string // Vergewissern Sie sich, dass alle Repos vorhanden sind und tatsächlich git-Repos (haben .git-Unterverzeichnis) für _, r: = range repo_names path: = root + r _, err: = os.Stat (path + "/.git") if err! = nil log.Fatal (err) repos = anhängen (Repos, Pfad)

Go verfügt über eine einzigartige Fehlerbehandlungsfunktion, bei der Funktionen häufig einen Rückgabewert und ein Fehlerobjekt zurückgeben. Wie das geht? os.Stat () gibt zwei Werte zurück. In diesem Fall wird der Platzhalter "_" zum Speichern des tatsächlichen Ergebnisses verwendet, da Sie sich nur um den Fehler kümmern. Go ist sehr streng und erfordert, dass benannte Variablen verwendet werden. Wenn Sie nicht vorhaben, einen Wert zu verwenden, sollten Sie ihn "_" zuweisen, um einen Kompilierungsfehler zu vermeiden.

Shell-Befehle ausführen

An diesem Punkt haben Sie eine Liste mit Repository-Pfaden, in denen Sie den Befehl git ausführen möchten. Wie Sie sich erinnern, haben wir die git-Befehlszeile als ein einzelnes Befehlszeilenargument (Flag) mit dem Namen "Befehl" erhalten. Dies muss in ein Array von Komponenten (git-Befehl, Unterbefehl und Optionen) aufgeteilt werden. Der gesamte Befehl als String wird ebenfalls zu Anzeigezwecken gespeichert.

 // Den git-Befehl in Komponenten aufteilen (zur Ausführung erforderlich) var git_components [] Zeichenfolge für _, component: = range strings.Split (* command, "") git_components = anhängen (git_components, component) command_string: = "git "+ * Befehl

Jetzt müssen Sie alle Repositorys durchlaufen und den Befehl git in jedem Repository ausführen. Das Schleifenkonstrukt "for ... range" wird erneut verwendet. Zuerst ändert Multi-Git sein Arbeitsverzeichnis in das aktuelle Ziel-Repo "r" und gibt den Befehl git aus. Dann führt es den Befehl mit der exec.Command () Funktion und Ausdruck der kombinierten Ausgabe (Standardausgabe und Standardfehler). 

Zum Schluss wird geprüft, ob bei der Ausführung ein Fehler aufgetreten ist. Wenn es einen Fehler gab und die ignoreErrors Flag ist falsch, dann tritt Multi-Git aus. Der Grund für das optionale Ignorieren von Fehlern ist, dass manchmal Fehler auftreten, wenn Befehle bei einigen Repos fehlschlagen. Wenn Sie zum Beispiel einen Zweig namens "Cool Feature" für alle Repositorys mit diesem Zweig auschecken möchten, ist es Ihnen egal, ob die Überprüfung für Repositorys ohne diesen Zweig fehlschlägt.

 für _, r: = range repos // Wechseln Sie in das Repos-Verzeichnis. os.Chdir (r); // Drucken Sie den Befehl fmt.Printf ("[% s]% s \ n", r, Befehlszeichenfolge) // Führen Sie den Befehl aus, err: = exec.Command ("git", git_components ...) .CombinedOutput () / / Ergebnis drucken fmt.Println (string (out)) // Fehlerbehebung bei Fehler und KEINE Fehler ignorieren, wenn err! = Nil &&! * IgnoreErrors os.Exit (1) fmt.Println ("Done . ")

Fazit

Go ist eine einfache, aber mächtige Sprache. Es ist für die Systemprogrammierung im großen Maßstab konzipiert, funktioniert aber auch für kleine Befehlszeilenprogramme. Gos minimalistisches Design steht im krassen Gegensatz zu anderen modernen Sprachen wie Scale und Rust, die sehr mächtig und gut gestaltet sind, aber eine sehr steile Lernkurve haben. Ich ermutige Sie, Go auszuprobieren und zu experimentieren. Es macht viel Spass.