Erstellen von Go-Anwendungen für verschiedene Betriebssysteme und Architekturen

Bei der Softwareentwicklung ist es wichtig, das operating system und den zugrunde liegenden Prozessor architecture zu berücksichtigen, die Sie möchten um deine Binärdatei für zu kompilieren. Da es häufig langsam oder unmöglich ist, eine Binärdatei auf einer anderen Betriebssystem- / Architekturplattform auszuführen, ist es gängige Praxis, die endgültige Binärdatei für viele verschiedene Plattformen zu erstellen, um die Zielgruppe Ihres Programms zu maximieren. Dies kann jedoch schwierig sein, wenn sich die Plattform, die Sie für die Entwicklung verwenden, von der Plattform unterscheidet, auf der Sie Ihr Programm bereitstellen möchten. In der Vergangenheit mussten zum Beispiel zum Entwickeln eines Programms unter Windows und zum Bereitstellen auf einem Linux- oder MacOS-Computer Build-Maschinen für jede der Umgebungen eingerichtet werden, für die Sie Binärdateien benötigen. Sie müssen außerdem Ihre Werkzeuge synchron halten, und dies zusätzlich zu anderen Überlegungen, die die Kosten erhöhen und das gemeinsame Testen und Verteilen erschweren.

Go löst dieses Problem, indem die Unterstützung für mehrere Plattformen direkt in das Tool "+ go build" sowie in den Rest der Go-Toolchain integriert wird. Unter Verwendung von environment variables und https: // Unter www.digitalocean.com/community/tutorials/customizing-go-binaries-with-build-tags[build tags] können Sie steuern, für welches Betriebssystem und welche Architektur Ihre endgültige Binärdatei erstellt wird. Außerdem können Sie einen Workflow zusammenstellen, der schnell funktioniert Schaltet die Einbeziehung von plattformabhängigem Code um, ohne die Codebasis zu ändern.

In diesem Tutorial stellen Sie eine Beispielanwendung zusammen, die strings zu einem Dateipfad zusammenfügt. Erstellen und selektieren Sie plattformabhängige Snippets und erstellen Sie Binärdateien für mehrere Betriebssysteme und Systemarchitekturen auf Ihrem eigenen System, um zu zeigen, wie Sie diese leistungsstarken Funktionen der Programmiersprache Go nutzen können.

Voraussetzungen

Um dem Beispiel in diesem Artikel zu folgen, benötigen Sie:

Mögliche Plattformen für + GOOS + und + GOARCH +

Bevor wir zeigen, wie der Erstellungsprozess zum Erstellen von Binärdateien für verschiedene Plattformen gesteuert wird, untersuchen wir zunächst, für welche Arten von Plattformen Go erstellt werden kann und wie Go diese Plattformen mit den Umgebungsvariablen "+ GOOS " und " GOARCH +" referenziert.

Das Go-Tool verfügt über einen Befehl, mit dem eine Liste der möglichen Plattformen gedruckt werden kann, auf denen Go aufbauen kann. Diese Liste kann sich mit jeder neuen Go-Version ändern, sodass die hier beschriebenen Kombinationen in einer anderen Go-Version möglicherweise nicht identisch sind. Zum Zeitpunkt der Erstellung dieses Tutorials ist die aktuelle Go-Version https://golang.org/doc/go1.13 [+ 1.13 +].

Führen Sie Folgendes aus, um diese Liste möglicher Plattformen zu finden:

go tool dist list

Sie erhalten eine Ausgabe ähnlich der folgenden:

Outputaix/ppc64        freebsd/amd64   linux/mipsle   openbsd/386
android/386      freebsd/arm     linux/ppc64    openbsd/amd64
android/amd64    illumos/amd64   linux/ppc64le  openbsd/arm
android/arm      js/wasm         linux/s390x    openbsd/arm64
android/arm64    linux/386       nacl/386       plan9/386
darwin/386       linux/amd64     nacl/amd64p32  plan9/amd64
darwin/amd64     linux/arm       nacl/arm       plan9/arm
darwin/arm       linux/arm64     netbsd/386     solaris/amd64
darwin/arm64     linux/mips      netbsd/amd64   windows/386
dragonfly/amd64  linux/mips64    netbsd/arm     windows/amd64
freebsd/386      linux/mips64le  netbsd/arm64   windows/arm

Diese Ausgabe besteht aus einer Reihe von Schlüssel-Wert-Paaren, die durch ein "+ / " getrennt sind. Der erste Teil der Kombination vor dem " / " ist das Betriebssystem. In Go sind diese Betriebssysteme mögliche Werte für die Umgebungsvariable " GOOS ", ausgesprochen "goose", die für "Go Operating System" steht. Der zweite Teil nach dem " / " ist die Architektur. Dies sind nach wie vor alle möglichen Werte für eine Umgebungsvariable: ` GOARCH +`. Dies wird "gore-ch" ausgesprochen und steht für "Go Architecture".

Lassen Sie uns eine dieser Kombinationen aufschlüsseln, um zu verstehen, was es bedeutet und wie es funktioniert, und zwar am Beispiel von "+ linux / 386 ". Das Schlüssel-Wert-Paar beginnt mit dem Zeichen " GOOS ", in diesem Beispiel " linux " (siehe https://www.digitalocean.com/community/tutorial_series/getting-started-with-linux[Linux) OS]. Das " GOARCH " hier wäre " 386 +", was für den "https://en.wikipedia.org/wiki/Intel_80386[Intel 80386 microprocessor" steht.

Es gibt viele Plattformen, die mit dem Befehl "+ go build" zur Verfügung stehen. Meistens verwenden Sie jedoch "+ linux ", " windows " oder " darwin " als Wert für " GOOSe". Diese decken die drei großen Betriebssystemplattformen ab: Linux, Windows und https: //en.wikipedia .org / wiki / MacOS [macOS], das auf dem Darwin operating system basiert und daher "+ darwin " heißt. Go kann jedoch auch weniger Mainstream-Plattformen wie " nacl +" abdecken, die Googles Native Client darstellen.

Wenn Sie einen Befehl wie "+ go build " ausführen, verwendet Go die aktuelle Plattform " GOOS" und "+ GOARCH", um zu bestimmen, wie die Binärdatei erstellt werden soll. Um herauszufinden, welche Kombination Ihre Plattform hat, können Sie den Befehl + go env + verwenden und + GOOS + und + GOARCH + als Argumente übergeben:

go env GOOS GOARCH

Beim Testen dieses Beispiels haben wir diesen Befehl unter macOS auf einem Computer mit einer AMD64 architecture ausgeführt, sodass wir die folgende Ausgabe erhalten:

Output

Hier sagt uns die Ausgabe des Befehls, dass unser System "+ GOOS = darwin " und " GOARCH = amd64 +" hat.

Sie wissen jetzt, was die Zeichen "+ GOOS " und " GOARCH +" in Go enthalten, sowie deren mögliche Werte. Als Nächstes stellen Sie ein Programm zusammen, das als Beispiel für die Verwendung dieser Umgebungsvariablen dient, und erstellen Tags, um Binärdateien für andere Plattformen zu erstellen.

Schreiben Sie ein plattformabhängiges Programm mit + filepath.Join () +

Bevor Sie mit dem Erstellen von Binärdateien für andere Plattformen beginnen, erstellen wir ein Beispielprogramm. Ein gutes Beispiel für diesen Zweck ist die Funktion + Join + im Paket https://godoc.org/path/filepath [+ path / filepath +] in der Go-Standardbibliothek. Diese Funktion akzeptiert mehrere Zeichenfolgen und gibt eine Zeichenfolge zurück, die mit dem richtigen Dateipfadtrennzeichen verbunden ist.

Dies ist ein gutes Beispielprogramm, da die Funktionsweise des Programms von dem Betriebssystem abhängt, auf dem es ausgeführt wird. Unter Windows ist das Pfadtrennzeichen ein umgekehrter Schrägstrich ("+ \ "), während Unix-basierte Systeme einen Schrägstrich (" / +") verwenden.

Beginnen wir mit der Erstellung einer Anwendung, die "+ filepath.Join () " verwendet, und schreiben später eine eigene Implementierung der Funktion " Join () +", mit der der Code an die plattformspezifischen Binärdateien angepasst wird.

Erstellen Sie zunächst einen Ordner in Ihrem + src + - Verzeichnis mit dem Namen Ihrer App:

mkdir

In dieses Verzeichnis verschieben:

cd

Als nächstes erstellen Sie eine neue Datei in Ihrem Texteditor Ihrer Wahl mit dem Namen "+ main.go +". Für dieses Tutorial verwenden wir Nano:

nano main.go

Fügen Sie nach dem Öffnen der Datei den folgenden Code hinzu:

src / app / main.go

package main

import (
 "fmt"
 "path/filepath"
)

func main() {
 s := filepath.Join("a", "b", "c")
 fmt.Println(s)
}

Die Funktion + main () + in dieser Datei verwendet + filepath.Join () +, um drei https://www.digitalocean.com/community/tutorials/an-introduction-to-working-with-strings zu verknüpfen -in-go [Strings] zusammen mit dem richtigen, plattformabhängigen Pfadtrennzeichen.

Speichern und beenden Sie die Datei und führen Sie das Programm aus:

go run main.go

Wenn Sie dieses Programm ausführen, erhalten Sie je nach verwendeter Plattform unterschiedliche Ausgaben. Unter Windows sehen Sie die durch "+ \ +" getrennten Zeichenfolgen:

Outputabc

Auf Unix-Systemen wie macOS und Linux erhalten Sie Folgendes:

Outputabc

Dies zeigt, dass das Programm aufgrund der unterschiedlichen Dateisystemprotokolle, die auf diesen Betriebssystemen verwendet werden, unterschiedlichen Code für die verschiedenen Plattformen erstellen muss. Da jedoch je nach Betriebssystem bereits ein anderes Dateitrennzeichen verwendet wird, wissen wir, dass "+ filepath.Join () " bereits den Unterschied in der Plattform ausmacht. Dies liegt daran, dass die Go-Toolkette die Zeichen " GOOS " und " GOARCH +" Ihres Computers automatisch erkennt und anhand dieser Informationen das Codefragment mit der richtigen https://www.digitalocean.com/community/tutorials/customizing-go- verwendet. Binärdateien mit Build-Tags [Build-Tags] und Dateitrennzeichen.

Überlegen wir uns, woher die Funktion + filepath.Join () + ihr Trennzeichen bezieht. Führen Sie den folgenden Befehl aus, um das entsprechende Snippet aus der Go-Standardbibliothek zu überprüfen:

less /usr/local/go/src/os/path_unix.go

Dies zeigt den Inhalt von + path_unix.go + an. Suchen Sie nach dem folgenden Teil der Datei:

/usr/local/go/os/path_unix.go

. . .


package os

const (
 PathSeparator     = '/' // OS-specific path separator
 PathListSeparator = ':' // OS-specific path list separator
)
. . .

Dieser Abschnitt definiert den "+ PathSeparator " für alle Arten von Unix-ähnlichen Systemen, die Go unterstützt. Beachten Sie alle Build-Tags oben, die jeweils eine der möglichen Unix-Plattformen ` GOOS ` darstellen, die mit Unix verknüpft sind. Wenn " GOOS +" mit diesen Begriffen übereinstimmt, liefert Ihr Programm das Dateipfad-Trennzeichen im Unix-Stil.

Drücken Sie + q +, um zur Befehlszeile zurückzukehren.

Öffnen Sie als nächstes die Datei, die das Verhalten von + filepath.Join () + unter Windows definiert:

less /usr/local/go/src/os/path_windows.go

Sie werden folgendes sehen:

/usr/local/go/os/path_unix.go

. . .
package os

const (
       PathSeparator     = '\\' // OS-specific path separator
       PathListSeparator = ';'  // OS-specific path list separator
)
. . .

Obwohl der Wert von "+ PathSeparator " hier " \\ " ist, gibt der Code den einzelnen Backslash (" \ +") wieder, der für Windows-Dateipfade benötigt wird, da der erste Backslash nur als Escape-Zeichen benötigt wird.

Beachten Sie, dass im Gegensatz zur Unix-Datei oben keine Build-Tags angezeigt werden. Dies liegt daran, dass "+ GOOS " und " GOARCH " auch an " go build " übergeben werden können, indem dem Dateinamen ein Unterstrich (" _ ") und die Umgebungsvariable als Suffix hinzugefügt werden Weitere Informationen finden Sie im Abschnitt https://www.digitalocean.com/community/tutorials/building-go-applications-for-different-operating-systems-and-architectures#using-goos-and-goarch-filename-suffixes[*Using Suffixe für GOOS- und GOARCH-Dateinamen *]. Hier bewirkt der Teil " _windows " von " path_windows.go ", dass die Datei so wirkt, als hätte sie das Build-Tag " // + build windows " oben in der Datei. Wenn Ihr Programm unter Windows ausgeführt wird, werden daher die Konstanten " PathSeparator " und " PathListSeparator " aus dem Code-Snippet " path_windows.go +" verwendet.

Um zur Befehlszeile zurückzukehren, beenden Sie "+ less " durch Drücken von " q +".

In diesem Schritt haben Sie ein Programm erstellt, in dem gezeigt wurde, wie Go die Zeichen "+ GOOS " und " GOARCH " automatisch in Build-Tags konvertiert. In diesem Sinne können Sie jetzt Ihr Programm aktualisieren und Ihre eigene Implementierung von " filepath.Join () " schreiben, indem Sie Build-Tags verwenden, um den richtigen " PathSeparator +" für Windows- und Unix-Plattformen manuell festzulegen.

Implementierung einer plattformspezifischen Funktion

Nachdem Sie nun wissen, wie die Standardbibliothek von Go plattformspezifischen Code implementiert, können Sie Build-Tags verwenden, um dies in Ihrem eigenen "+" - Programm zu tun. Dazu schreiben Sie Ihre eigene Implementierung von ` filepath.Join () +`.

Öffnen Sie Ihre + main.go + Datei:

nano main.go

Ersetzen Sie den Inhalt von "+ main.go " durch den folgenden mit Ihrer eigenen Funktion " Join () +":

src / app / main.go

package main

import (
 "fmt"
 "strings"
)

func Join(parts ...string) string {
 return strings.Join(parts, PathSeparator)
}

func main() {
 s := Join("a", "b", "c")
 fmt.Println(s)
}

Die Funktion "+ Join " nimmt eine Reihe von " parts " und verbindet sie mithilfe der https://godoc.org/strings.Join [` strings.Join () `] -Methode aus dem https: // www .digitalocean.com / community / tutorials / eine-einführung-in-das-strings-package-in-go [` strings ` package], um die ` parts ` mit dem ` PathSeparator +` zu verketten.

Sie haben den "+ PathSeparator " noch nicht definiert. Tun Sie dies jetzt in einer anderen Datei. Speichern und beenden Sie " main.go ", öffnen Sie Ihren bevorzugten Editor und erstellen Sie eine neue Datei mit dem Namen " path.go +":

nano path.go

Definieren Sie das "+ PathSeparator " und setzen Sie es gleich dem Unix-Dateipfad-Trennzeichen " / +":

src / app / path.go

package main

const PathSeparator = "/"

Kompilieren Sie die Anwendung und führen Sie sie aus:

go build
./app

Sie erhalten folgende Ausgabe:

Outputa/b/c

Dies wird erfolgreich ausgeführt, um einen Dateipfad im Unix-Stil zu erhalten. Dies ist jedoch noch nicht das, was wir wollen: Die Ausgabe ist immer "+ a / b / c +", unabhängig davon, auf welcher Plattform sie ausgeführt wird. Um die Funktionalität zum Erstellen von Windows-ähnlichen Dateipfaden hinzuzufügen, müssen Sie eine Windows-Version des PathSeparator hinzufügen und dem Befehl go build mitteilen, welche Version verwendet werden soll. Im nächsten Abschnitt verwenden Sie build tags, um dies zu erreichen.

Mit + GOOS + oder + GOARCH + Tags erstellen

Um Windows-Plattformen zu berücksichtigen, erstellen Sie jetzt eine alternative Datei zu "+ path.go " und verwenden Build-Tags, um sicherzustellen, dass die Code-Snippets nur ausgeführt werden, wenn " GOOS " und " GOARCH +" die geeignete Plattform sind.

Fügen Sie jedoch zuerst ein Build-Tag zu "+ path.go +" hinzu, damit es für alles außer Windows erstellt wird. Öffnen Sie die Datei:

nano path.go

Fügen Sie der Datei das folgende hervorgehobene Build-Tag hinzu:

src / app / path.go

package main

const PathSeparator = "/"

Go-Build-Tags ermöglichen das Invertieren, dh Sie können Go anweisen, diese Datei für alle Plattformen außer Windows zu erstellen. Um ein Build-Tag umzukehren, setzen Sie ein "+! +" Vor das Tag.

Speichern und schließen Sie die Datei.

Wenn Sie dieses Programm unter Windows ausführen, wird folgende Fehlermeldung angezeigt:

Output./main.go:9:29: undefined: PathSeparator

In diesem Fall kann Go "+ path.go " nicht einschließen, um die Variable " PathSeparator +" zu definieren.

Nachdem Sie sichergestellt haben, dass "+ path.go " nicht ausgeführt wird, wenn " GOOS " unter Windows ausgeführt wird, fügen Sie eine neue Datei " windows.go +" hinzu:

nano windows.go

Definieren Sie in "+ windows.go " den Windows " PathSeparator " sowie ein Build-Tag, um dem Befehl " go build +" mitzuteilen, dass es sich um die Windows-Implementierung handelt:

src / app / windows.go

// +build windows

package main

const PathSeparator = "\\"

Speichern Sie die Datei und beenden Sie den Texteditor. Die Anwendung kann jetzt eine Möglichkeit für Windows und eine andere für alle anderen Plattformen kompilieren.

Während die Binärdateien nun korrekt für ihre Plattformen erstellt werden, müssen Sie weitere Änderungen vornehmen, um eine Plattform zu kompilieren, auf die Sie keinen Zugriff haben. Dazu ändern Sie im nächsten Schritt Ihre lokalen Umgebungsvariablen "+ GOOS " und " GOARCH +".

Verwenden Ihrer lokalen Umgebungsvariablen + GOOS + und + GOARCH +

Zuvor haben Sie den Befehl + go env GOOS GOARCH + ausgeführt, um herauszufinden, an welchem ​​Betriebssystem und welcher Architektur Sie gearbeitet haben. Wenn Sie den Befehl + go env + ausführen, werden die beiden Umgebungsvariablen + GOOS + und + GOARCH + gesucht. Wenn sie gefunden werden, werden ihre Werte verwendet. Wenn sie nicht gefunden werden, werden sie von Go mit den Informationen für die aktuelle Plattform festgelegt. Dies bedeutet, dass Sie "+ GOOS " oder " GOARCH +" ändern können, damit sie nicht standardmäßig auf Ihr lokales Betriebssystem und Ihre lokale Architektur angewendet werden.

Der Befehl + go build verhält sich ähnlich wie der Befehl` + go env`. Sie können entweder die Umgebungsvariablen + GOOS + oder + GOARCH + so einstellen, dass sie mit + go build + für eine andere Plattform erstellt werden.

Wenn Sie kein Windows-System verwenden, erstellen Sie eine + windows + Binärdatei von ++, indem Sie die Umgebungsvariable + GOOS + auf + windows + setzen, wenn Sie den Befehl + go build + ausführen:

GOOS=windows go build

Listen Sie nun die Dateien in Ihrem aktuellen Verzeichnis auf:

ls

Die Ausgabe der Auflistung des Verzeichnisses zeigt, dass es jetzt eine ausführbare Datei für + app.exe + Windows im Projektverzeichnis gibt:

Outputapp    main.go  path.go  windows.go

Mit dem Befehl + file + können Sie weitere Informationen zu dieser Datei abrufen und deren Erstellung bestätigen:

file app.exe

Du wirst erhalten:

Outputapp.exe: PE32+ executable (console) x86-64 (stripped to external PDB),

Sie können auch eine oder beide Umgebungsvariablen zur Erstellungszeit festlegen. Führen Sie Folgendes aus:

GOOS=linux GOARCH=ppc64 go build

Ihre "+" - Programmdatei wird jetzt durch eine Datei für eine andere Architektur ersetzt. Führen Sie den Befehl " file" für diese Binärdatei aus:

file app

Sie erhalten eine Ausgabe wie die folgende:

app: ELF 64-bit MSB executable, , version 1 (SYSV), statically linked, not stripped

Indem Sie Ihre lokalen Umgebungsvariablen "+ GOOS " und " GOARCH +" festlegen, können Sie jetzt Binärdateien für alle Go-kompatiblen Plattformen ohne komplizierte Konfiguration oder Einrichtung erstellen. Als Nächstes verwenden Sie Dateinamenkonventionen, um Ihre Dateien übersichtlich zu halten und für bestimmte Plattformen automatisch ohne Build-Tags zu erstellen.

Verwenden von + GOOS + und + GOARCH + Dateinamensuffixen

Wie Sie bereits gesehen haben, werden in der Go-Standardbibliothek häufig Build-Tags verwendet, um den Code zu vereinfachen, indem verschiedene Plattformimplementierungen in verschiedene Dateien aufgeteilt werden. Als Sie die Datei "+ os / path_unix.go " öffneten, gab es ein Build-Tag, das alle möglichen Kombinationen auflistete, die als Unix-ähnliche Plattformen gelten. Die Datei " os / path_windows.go +" enthielt jedoch keine Build-Tags, da das Suffix im Dateinamen ausreichte, um Go mitzuteilen, für welche Plattform die Datei bestimmt war.

Sehen wir uns die Syntax dieser Funktion an. Wenn Sie eine "+ .go " - Datei benennen, können Sie " GOOS " und " GOARCH " als Suffixe zum Dateinamen in dieser Reihenfolge hinzufügen und die Werte durch Unterstriche (" _ ") trennen. Wenn Sie eine Go-Datei mit dem Namen " filename.go " hatten, können Sie das Betriebssystem und die Architektur angeben, indem Sie den Dateinamen in " filename __. Go " ändern. Wenn Sie es beispielsweise für Windows mit der 64-Bit-Version https://en.wikipedia.org/wiki/ARM_architecture[ARM architecture] kompilieren möchten, geben Sie den Namen der Datei " filename_windows_arm64.go +" an. Diese Namenskonvention hilft dabei, den Code übersichtlich zu halten.

Aktualisieren Sie Ihr Programm, um die Dateinamensuffixe anstelle von Build-Tags zu verwenden. Benennen Sie zuerst die Dateien + path.go + und + windows.go + um, um die im Paket + os + verwendete Konvention zu verwenden:

mv path.go path_unix.go
mv windows.go path_windows.go

Wenn die beiden Dateinamen geändert wurden, können Sie das Build-Tag entfernen, das Sie zu + path_windows.go + hinzugefügt haben:

nano path_windows.go

Entfernen Sie + // + build windows +, damit Ihre Datei so aussieht:

path_windows.go

package main

const PathSeparator = "\\"

Speichern und beenden Sie die Datei.

Da + unix + kein gültiges + GOOS + ist, hat das Suffix + _unix.go + keine Bedeutung für den Go-Compiler. Es vermittelt jedoch den beabsichtigten Zweck der Datei. Wie die Datei "+ os / path_unix.go " muss auch die Datei " path_unix.go +" Build-Tags verwenden. Lassen Sie diese Datei also unverändert.

Durch die Verwendung von Dateinamenkonventionen entfernen Sie nicht benötigte Build-Tags aus Ihrem Quellcode und machen das Dateisystem übersichtlicher und übersichtlicher.

Fazit

Die Möglichkeit, Binärdateien für mehrere Plattformen zu generieren, für die keine Abhängigkeiten erforderlich sind, ist eine leistungsstarke Funktion der Go-Toolchain. In diesem Lernprogramm haben Sie diese Funktion verwendet, indem Sie Build-Tags und Dateinamensuffixe hinzugefügt haben, um bestimmte Codeausschnitte zu markieren, die nur für bestimmte Architekturen kompiliert werden sollen. Sie haben Ihr eigenes platorm-abhängiges Programm erstellt und dann die Umgebungsvariablen "+ GOOS" und "+ GOARCH" bearbeitet, um Binärdateien für Plattformen außerhalb Ihrer aktuellen Plattform zu generieren. Dies ist eine wertvolle Fähigkeit, da es allgemein üblich ist, einen kontinuierlichen Integrationsprozess durchzuführen, der diese Umgebungsvariablen automatisch durchläuft, um Binärdateien für alle Plattformen zu erstellen.

Weitere Informationen zu + go build + finden Sie in unserem Customizing Go Binaries with Build Tags Tutorial. Wenn Sie mehr über die Programmiersprache Go im Allgemeinen erfahren möchten, lesen Sie die gesamte How To Code in Go series .