Einführung
Wenn Sie Anwendungen in einer Produktionsumgebung bereitstellen, können Sie durch Erstellen von Binärdateien mit Versionsinformationen und anderen Metadaten Ihre Überwachungs-, Protokollierungs- und Debugging-Prozesse verbessern, indem Sie Identifizierungsinformationen hinzufügen, um Ihre Builds im Laufe der Zeit zu verfolgen. Diese Versionsinformationen können häufig hochdynamische Daten enthalten, z. B. die Erstellungszeit, den Computer oder Benutzer, der die Binärdatei erstellt, die Commit-ID vonVersion Control System (VCS), für die er erstellt wurde, und vieles mehr. Da sich diese Werte ständig ändern, ist das Codieren dieser Daten direkt in den Quellcode und das Ändern vor jedem neuen Build mühsam und fehleranfällig: Quelldateien können sich verschieben undvariables/constants können während der Entwicklung die Dateien wechseln, wodurch der Erstellungsprozess unterbrochen wird .
Eine Möglichkeit, dies in Go zu lösen, besteht darin,-ldflags
mit dem Befehlgo build
zu verwenden, um dynamische Informationen zur Erstellungszeit in die Binärdatei einzufügen, ohne dass eine Änderung des Quellcodes erforderlich ist. In diesem Flag stehtld
fürlinker, das Programm, das die verschiedenen Teile des kompilierten Quellcodes in der endgültigen Binärdatei miteinander verbindet. ldflags
steht dann fürlinker flags. Dies wird genannt, weil es ein Flag an den zugrunde liegenden Go-Toolchain-Linkercmd/link
übergibt, mit dem Sie die Werte importierter Pakete zur Erstellungszeit über die Befehlszeile ändern können.
In diesem Lernprogramm verwenden Sie-ldflags
, um den Wert von Variablen zur Erstellungszeit zu ändern und Ihre eigenen dynamischen Informationen mithilfe einer Beispielanwendung, die Versionsinformationen auf dem Bildschirm druckt, in eine Binärdatei einzufügen.
Voraussetzungen
Um dem Beispiel in diesem Artikel zu folgen, benötigen Sie:
-
Ein Go-Arbeitsbereich, der durch Befolgen vonHow To Install Go and Set Up a Local Programming Environment eingerichtet wurde.
Erstellen Ihrer Beispielanwendung
Bevor Sieldflags
verwenden können, um dynamische Daten einzuführen, benötigen Sie zunächst eine Anwendung, in die Sie die Informationen einfügen können. In diesem Schritt erstellen Sie diese Anwendung, die zu diesem Zeitpunkt nur statische Versionsinformationen ausgibt. Lassen Sie uns diese Anwendung jetzt erstellen.
Erstellen Sie in Ihrem Verzeichnissrc
ein Verzeichnis, das nach Ihrer Anwendung benannt ist. In diesem Tutorial wird der Anwendungsnameapp
verwendet:
mkdir app
Ändern Sie Ihr Arbeitsverzeichnis in diesen Ordner:
cd app
Erstellen Sie als Nächstes mit dem Texteditor Ihrer Wahl den Einstiegspunkt Ihres Programms,main.go
:
nano main.go
Lassen Sie Ihre Anwendung jetzt die Versionsinformationen ausdrucken, indem Sie die folgenden Inhalte hinzufügen:
app/main.go
package main
import (
"fmt"
)
var Version = "development"
func main() {
fmt.Println("Version:\t", Version)
}
Innerhalb der Funktionmain()
haben Sie die VariableVersion
deklariert und dann diestringVersion:
gedruckt, gefolgt von einem Tabulatorzeichen,
und der deklarierten Variable.
Zu diesem Zeitpunkt ist die VariableVersion
alsdevelopment
definiert. Dies ist die Standardversion für diese App. Später werden Sie diesen Wert in eine offizielle Versionsnummer ändern, die nachsemantic versioning format geordnet ist.
Speichern und schließen Sie die Datei. Erstellen Sie anschließend die Anwendung und führen Sie sie aus, um sicherzustellen, dass die richtige Version gedruckt wird:
go build
./app
Sie werden die folgende Ausgabe sehen:
OutputVersion: development
Sie haben jetzt eine Anwendung, die Standardversionsinformationen druckt, aber Sie haben noch keine Möglichkeit, die aktuellen Versionsinformationen zum Zeitpunkt der Erstellung weiterzugeben. Im nächsten Schritt verwenden Sie-ldflags
undgo build
, um dieses Problem zu lösen.
Verwenden vonldflags
mitgo build
Wie bereits erwähnt, stehtldflags
fürlinker flags und wird verwendet, um Flags an den zugrunde liegenden Linker in der Go-Toolchain zu übergeben. Dies funktioniert nach folgender Syntax:
go build -ldflags="-flag"
In diesem Beispiel haben wirflag
an den zugrunde liegenden Befehlgo tool link
übergeben, der als Teil vongo build
ausgeführt wird. Dieser Befehl verwendet doppelte Anführungszeichen um den anldflags
übergebenen Inhalt, um zu vermeiden, dass darin enthaltene Zeichen oder Zeichen, die die Befehlszeile möglicherweise als etwas anderes als das von uns gewünschte interpretiert, beschädigt werden. Von hier aus können Siemany different link
flags übergeben. Für die Zwecke dieses Tutorials verwenden wir das Flag-X
, um Informationen zur Verknüpfungszeit in die Variable zu schreiben, gefolgt vom Pfadpackagezur Variablen und ihrem neuen Wert:
go build -ldflags="-X 'package_path.variable_name=new_value'"
In den Anführungszeichen gibt es jetzt die Option-X
undkey-value pair, die die zu ändernde Variable und ihren neuen Wert darstellen. Das Zeichen.
trennt den Paketpfad und den Variablennamen, und einfache Anführungszeichen werden verwendet, um zu vermeiden, dass Zeichen im Schlüssel-Wert-Paar unterbrochen werden.
Um die VariableVersion
in Ihrer Beispielanwendung zu ersetzen, verwenden Sie die Syntax im letzten Befehlsblock, um einen neuen Wert zu übergeben und die neue Binärdatei zu erstellen:
go build -ldflags="-X 'main.Version=v1.0.0'"
In diesem Befehl istmain
der Paketpfad der VariablenVersion
, da sich diese Variable in der Dateimain.go
befindet. Version
ist die Variable, in die Sie schreiben, undv1.0.0
ist der neue Wert.
Umldflags
verwenden zu können, muss der Wert, den Sie ändern möchten, vorhanden sein und eine Variable auf Paketebene vom Typstring
sein. Diese Variable kann entweder exportiert oder nicht exportiert werden. Der Wert darf nichtconst
sein oder durch das Ergebnis eines Funktionsaufrufs festgelegt werden. Glücklicherweise erfülltVersion
alle diese Anforderungen: Es wurde bereits in der Dateimain.go
als Variable deklariert, und der aktuelle Wert (development
) und der gewünschte Wert (v1.0.0
) sind beide Saiten.
Führen Sie die Anwendung aus, sobald die Binärdatei Ihres neuenapp
erstellt wurde:
./app
Sie erhalten folgende Ausgabe:
OutputVersion: v1.0.0
Mit-ldflags
haben Sie die VariableVersion
erfolgreich vondevelopment
inv1.0.0
geändert.
Sie haben jetzt einestring
-Variable in einer einfachen Anwendung zur Erstellungszeit geändert. Mitldflags
können Sie Versionsdetails, Lizenzinformationen und mehr in eine Binärdatei einbetten, die nur über die Befehlszeile zur Verteilung bereit ist.
In diesem Beispiel befand sich die von Ihnen geänderte Variable im Programmmain
, wodurch die Schwierigkeit beim Ermitteln des Pfadnamens verringert wurde. Manchmal ist es jedoch komplizierter, den Pfad zu diesen Variablen zu finden. Im nächsten Schritt schreiben Sie Werte in Variablen in Unterpaketen, um die beste Methode zur Ermittlung komplexerer Paketpfade zu demonstrieren.
Targeting von Unterpaketvariablen
Im letzten Abschnitt haben Sie die VariableVersion
bearbeitet, die sich im obersten Paket der Anwendung befand. Dies ist jedoch nicht immer der Fall. Oft ist es praktischer, diese Variablen in einem anderen Paket zu platzieren, damain
kein importierbares Paket ist. Um dies in Ihrer Beispielanwendung zu simulieren, erstellen Sie ein neues Unterpaket,app/build
, in dem Informationen zum Zeitpunkt der Erstellung der Binärdatei und zum Namen des Benutzers gespeichert werden, der den Befehl build erstellt hat.
Um ein neues Unterpaket hinzuzufügen, fügen Sie Ihrem Projekt zunächst ein neues Verzeichnis mit dem Namenbuild
hinzu:
mkdir -p build
Erstellen Sie dann eine neue Datei mit dem Namenbuild.go
, die die neuen Variablen enthält:
nano build/build.go
Fügen Sie in Ihrem Texteditor neue Variablen fürTime
undUser
hinzu:
app/build/build.go
package build
var Time string
var User string
Die VariableTime
enthält eine Zeichenfolgendarstellung der Zeit, zu der die Binärdatei erstellt wurde. Die VariableUser
enthält den Namen des Benutzers, der die Binärdatei erstellt hat. Da diese beiden Variablen immer Werte haben, müssen Sie diese Variablen nicht wie beiVersion
mit Standardwerten initialisieren.
Speichern und schließen Sie die Datei.
Öffnen Sie als Nächstesmain.go
, um diese Variablen zu Ihrer Anwendung hinzuzufügen:
nano main.go
Fügen Sie innerhalb vonmain.go
die folgenden hervorgehobenen Zeilen hinzu:
main.go
package main
import (
"app/build"
"fmt"
)
var Version = "development"
func main() {
fmt.Println("Version:\t", Version)
fmt.Println("build.Time:\t", build.Time)
fmt.Println("build.User:\t", build.User)
}
In diesen Zeilen haben Sie zuerst das Paketapp/build
importiert und dannbuild.Time
undbuild.User
auf dieselbe Weise gedruckt, wie SieVersion
gedruckt haben.
Speichern Sie die Datei und beenden Sie dann Ihren Texteditor.
Um auf diese Variablen mitldflags
abzuzielen, können Sie den Importpfadapp/build
gefolgt von.User
oder.Time
verwenden, da Sie den Importpfad bereits kennen. Um jedoch eine komplexere Situation zu simulieren, in der der Pfad zur Variablen nicht ersichtlich ist, verwenden wir stattdessen den Befehlnm
in der Go-Werkzeugkette.
Der Befehlgo tool nm
gibt diesymbols aus, die an einer bestimmten ausführbaren Datei, Objektdatei oder einem bestimmten Archiv beteiligt sind. In diesem Fall bezieht sich ein Symbol auf ein Objekt im Code, z. B. eine definierte oder importierte Variable oder Funktion. Durch Generieren einer Symboltabelle mitnm
und Verwenden vongrep
zum Suchen nach einer Variablen können Sie schnell Informationen über ihren Pfad finden.
[.note] #Note: Der Befehlnm
hilft Ihnen nicht, den Pfad Ihrer Variablen zu finden, wenn der Paketname nicht https: //en.wikipedia.org/wiki/ASCII [ASCII ] Zeichen oder ein"
oder%
Zeichen, da dies eine Einschränkung des Werkzeugs selbst darstellt.
#
Um diesen Befehl zu verwenden, erstellen Sie zuerst die Binärdatei fürapp
:
go build
Nachdemapp
erstellt wurde, richten Sie das Werkzeugnm
darauf und durchsuchen Sie die Ausgabe:
go tool nm ./app | grep app
Beim Ausführen gibt das Toolnm
viele Daten aus. Aus diesem Grund verwendete der vorhergehende Befehl|
, um die Ausgabe an den Befehlgrep
weiterzuleiten, der dann nach Begriffen suchte, deren Titel die oberste Ebeneapp
enthielt.
Sie erhalten eine Ausgabe ähnlich der folgenden:
Output 55d2c0 D app/build.Time
55d2d0 D app/build.User
4069a0 T runtime.appendIntStr
462580 T strconv.appendEscapedRune
. . .
In diesem Fall enthalten die ersten beiden Zeilen der Ergebnismenge die Pfade zu den beiden gesuchten Variablen:app/build.Time
undapp/build.User
.
Nachdem Sie die Pfade kennen, erstellen Sie die Anwendung erneut. Diesmal ändern SieVersion
,User
undTime
zur Erstellungszeit. Übergeben Sie dazu mehrere-X
Flags an-ldflags
:
go build -v -ldflags="-X 'main.Version=v1.0.0' -X 'app/build.User=$(id -u -n)' -X 'app/build.Time=$(date)'"
Hier haben Sie den Befehlid -u -n
Bash übergeben, um den aktuellen Benutzer aufzulisten, und den Befehldate
, um das aktuelle Datum aufzulisten.
Nachdem die ausführbare Datei erstellt wurde, führen Sie das Programm aus:
./app
Dieser Befehl erzeugt bei Ausführung auf einem Unix-System eine ähnliche Ausgabe wie der folgende:
OutputVersion: v1.0.0
build.Time: Fri Oct 4 19:49:19 UTC 2019
build.User: sammy
Jetzt verfügen Sie über eine Binärdatei mit Versions- und Build-Informationen, die Sie bei der Lösung von Problemen in der Produktion unterstützen können.
Fazit
Dieses Tutorial hat gezeigt, wieldflags
bei korrekter Anwendung ein leistungsstarkes Werkzeug zum Einfügen wertvoller Informationen in Binärdateien zur Erstellungszeit sein kann. Auf diese Weise können Sie Feature-Flags, Umgebungsinformationen, Versionsinformationen usw. steuern, ohne Änderungen an Ihrem Quellcode vornehmen zu müssen. Durch Hinzufügen vonldflags
zu Ihrem aktuellen Build-Workflow können Sie die Vorteile des in sich geschlossenen binären Verteilungsformats von Go maximieren.
Wenn Sie mehr über die Programmiersprache Go erfahren möchten, lesen Sie unsere vollständigenHow To Code in Go series. Wenn Sie nach weiteren Lösungen für die Versionskontrolle suchen, lesen Sie unserHow To Use Git-Referenzhandbuch.