Go Flag Bibliothek: Eine vollständige Anleitung zu CLI Argumenten
James Reed
Infrastructure Engineer · Leapcell

Einführung
flag
wird verwendet, um Befehlszeilenoptionen zu parsen. Personen mit Erfahrung in Unix-ähnlichen Systemen sollten mit Befehlszeilenoptionen vertraut sein. Zum Beispiel listet der Befehl ls -al
detaillierte Informationen über alle Dateien und Verzeichnisse im aktuellen Verzeichnis auf, wobei -al
die Befehlszeilenoption ist.
Befehlszeilenoptionen werden häufig in der tatsächlichen Entwicklung verwendet, insbesondere beim Schreiben von Tools.
- Geben Sie den Pfad der Konfigurationsdatei an. Zum Beispiel startet
postgres -D /usr/local/pgsql/data
den PostgreSQL-Server mit dem angegebenen Datenverzeichnis; - Passen Sie bestimmte Parameter an. Zum Beispiel startet
python -m SimpleHTTPServer 8080
einen HTTP-Server, der auf Port 8080 hört. Wenn nicht angegeben, hört er standardmäßig auf Port 8000.
Schnellstart
Der erste Schritt beim Erlernen einer Bibliothek ist natürlich die Verwendung. Werfen wir zunächst einen Blick auf die grundlegende Verwendung der flag
-Bibliothek:
package main import ( "fmt" "flag" ) var ( intflag int boolflag bool stringflag string ) func init() { flag.IntVar(&intflag, "intflag", 0, "int flag value") flag.BoolVar(&boolflag, "boolflag", false, "bool flag value") flag.StringVar(&stringflag, "stringflag", "default", "string flag value") } func main() { flag.Parse() fmt.Println("int flag:", intflag) fmt.Println("bool flag:", boolflag) fmt.Println("string flag:", stringflag) }
Sie können das Programm zuerst kompilieren und dann ausführen (ich verwende macOS):
$ go build -o main main.go $ ./main -intflag 12 -boolflag 1 -stringflag test
Ausgabe:
int flag: 12
bool flag: true
string flag: test
Wenn Sie eine bestimmte Option nicht festlegen, nimmt die entsprechende Variable den Standardwert an:
$ ./main -intflag 12 -boolflag 1
Ausgabe:
int flag: 12
bool flag: true
string flag: default
Sie können sehen, dass die Option stringflag
, die nicht gesetzt wurde, den Standardwert default
hat.
Sie können auch direkt go run
verwenden. Dieser Befehl kompiliert zuerst das Programm, um eine ausführbare Datei zu generieren, und führt dann die Datei aus, wobei andere Optionen in der Befehlszeile an dieses Programm übergeben werden.
$ go run main.go -intflag 12 -boolflag 1
Sie können -h
verwenden, um die Hilfsinformationen für die Option anzuzeigen:
$ ./main -h Usage of /path/to/main: -boolflag bool flag value -intflag int int flag value -stringflag string string flag value (default "default")
Zusammenfassend sind die allgemeinen Schritte zur Verwendung der flag
-Bibliothek:
- Definieren Sie einige globale Variablen, um die Werte der Optionen zu speichern, wie z.B.
intflag
,boolflag
undstringflag
hier; - Verwenden Sie die Methode
flag.TypeVar
in derinit
-Methode, um die Optionen zu definieren. Hier kannType
ein grundlegender Typ wieInt
,Uint
,Float64
,Bool
sein oder es kann auch ein Zeitintervalltime.Duration
sein. Übergeben Sie bei der Definition die Adresse der Variablen, den Optionsnamen, den Standardwert und die Hilfsinformationen; - Rufen Sie
flag.Parse
in dermain
-Methode auf, um die Optionen vonos.Args[1:]
zu parsen. Daos.Args[0]
der Pfad des ausführbaren Programms ist, wird er ausgeschlossen.
Zu beachtende Punkte
Die Methode flag.Parse
muss aufgerufen werden, nachdem alle Optionen definiert wurden, und es können keine neuen Optionen definiert werden, nachdem flag.Parse
aufgerufen wurde. Wenn Sie die vorherigen Schritte befolgen, wird es grundsätzlich keine Probleme geben.
Da init
vor dem gesamten Code ausgeführt wird, werden durch das Platzieren aller Optionsdefinitionen in init
bereits alle Optionen definiert, wenn flag.Parse
in der main
-Funktion ausgeführt wird.
Optionsformat
Die flag
-Bibliothek unterstützt drei Befehlszeilenoptionsformate.
-flag
-flag=x
-flag x
Sowohl -
als auch --
können verwendet werden und haben die gleiche Funktion. Einige Bibliotheken verwenden -
, um kurze Optionen darzustellen, und --
, um lange Optionen darzustellen. Relativ gesehen ist flag
einfacher zu verwenden.
Die erste Form unterstützt nur boolesche Optionen. Wenn sie erscheint, ist sie true
, und wenn sie nicht erscheint, nimmt sie den Standardwert an.
Die dritte Form unterstützt keine booleschen Optionen. Da boolesche Optionen in dieser Form in Unix-ähnlichen Systemen unerwartetes Verhalten zeigen können. Betrachten Sie den folgenden Befehl:
cmd -x *
Hier ist *
ein Shell-Wildcard. Wenn es Dateien mit den Namen 0
oder false
gibt, nimmt die boolesche Option -x
den Wert false
an. Andernfalls nimmt die boolesche Option -x
den Wert true
an. Und diese Option verbraucht ein Argument.
Wenn Sie eine boolesche Option explizit auf false
setzen möchten, können Sie nur die Form -flag=false
verwenden.
Das Parsen stoppt, wenn das erste Nicht-Optionsargument (d.h. ein Argument, das nicht mit -
oder --
beginnt) oder der Terminator --
gefunden wird. Führen Sie das folgende Programm aus:
$ ./main noflag -intflag 12
Die Ausgabe wird sein:
int flag: 0
bool flag: false
string flag: default
Da das Parsen stoppt, wenn es auf noflag
trifft, und die nachfolgende Option -intflag
nicht geparst wird. Daher nehmen alle Optionen ihre Standardwerte an.
Führen Sie das folgende Programm aus:
$ ./main -intflag 12 -- -boolflag=true
Die Ausgabe wird sein:
int flag: 12
bool flag: false
string flag: default
Zuerst wird die Option intflag
geparst und ihr Wert auf 12 gesetzt. Nach dem Auffinden von --
stoppt das Parsen, und das nachfolgende --boolflag=true
wird nicht geparst, so dass die Option boolflag
den Standardwert false
annimmt.
Nachdem das Parsen gestoppt wurde, speichert die flag
-Bibliothek diese, falls noch Befehlszeilenargumente vorhanden sind, und Sie können einen Slice dieser Argumente über die Methode flag.Args
erhalten.
Sie können die Anzahl der ungeparsten Argumente über die Methode flag.NArg
erhalten, und das Argument an Position i
(beginnend bei 0) über flag.Arg(i)
aufrufen.
Die Anzahl der Optionen kann auch durch Aufrufen der Methode flag.NFlag
erhalten werden.
Ändern Sie das obige Programm geringfügig:
func main() { flag.Parse() fmt.Println(flag.Args()) fmt.Println("Non-Flag Argument Count:", flag.NArg()) for i := 0; i < flag.NArg(); i++ { fmt.Printf("Argument %d: %s\n", i, flag.Arg(i)) } fmt.Println("Flag Count:", flag.NFlag()) }
Kompilieren und führen Sie dieses Programm aus:
$ go build -o main main.go $ ./main -intflag 12 -- -stringflag test
Ausgabe:
[-stringflag test]
Non-Flag Argument Count: 2
Argument 0: -stringflag
Argument 1: test
Nachdem das Parsen stoppt, wenn es auf --
trifft, werden die verbleibenden Argumente -stringflag test
in flag
gespeichert, und Sie können über Methoden wie Args
, NArg
und Arg
darauf zugreifen.
Integer-Optionswerte können Formen wie 1234
(dezimal), 0664
(oktal) und 0x1234
(hexadezimal) akzeptieren und können auch negativ sein. Tatsächlich verwendet flag
intern die Methode strconv.ParseInt
, um die Zeichenkette in ein int
zu parsen.
Also ist theoretisch jedes von ParseInt
akzeptierte Format in Ordnung.
Boolesche Optionswerte können sein:
- Werte für
true
:1
,t
,T
,true
,TRUE
,True
; - Werte für
false
:0
,f
,F
,false
,FALSE
,False
.
Eine andere Möglichkeit, Optionen zu definieren
Oben haben wir die Verwendung von flag.TypeVar
zur Definition von Optionen vorgestellt. Diese Methode erfordert, dass wir zuerst die Variable definieren und dann die Adresse der Variablen übergeben.
Es gibt noch eine andere Möglichkeit. Durch Aufrufen von flag.Type
(wobei Type
Int
, Uint
, Bool
, Float64
, String
, Duration
usw. sein kann) wird automatisch eine Variable für uns zugewiesen und die Adresse dieser Variablen zurückgegeben. Die Verwendung ist ähnlich wie bei der vorherigen Methode:
package main import ( "fmt" "flag" ) var ( intflag *int boolflag *bool stringflag *string ) func init() { intflag = flag.Int("intflag", 0, "int flag value") boolflag = flag.Bool("boolflag", false, "bool flag value") stringflag = flag.String("stringflag", "default", "string flag value") } func main() { flag.Parse() fmt.Println("int flag:", *intflag) fmt.Println("bool flag:", *boolflag) fmt.Println("string flag:", *stringflag) }
Kompilieren und führen Sie das Programm aus:
$ go build -o main main.go $ ./main -intflag 12
Die Ausgabe wird sein:
int flag: 12
bool flag: false
string flag: default
Abgesehen davon, dass beim Verwenden eine Dereferenzierung erforderlich ist, ist es im Grunde das gleiche wie bei der vorherigen Methode.
Erweiterte Verwendung
Definieren von Kurzoptionen
Die flag
-Bibliothek unterstützt Kurzoptionen nicht explizit, aber dies kann erreicht werden, indem verschiedene Optionen für dieselbe Variable festgelegt werden. Das heißt, zwei Optionen teilen sich dieselbe Variable.
Da die Initialisierungsreihenfolge ungewiss ist, muss sichergestellt werden, dass sie den gleichen Standardwert haben. Andernfalls ist das Verhalten ungewiss, wenn diese Option nicht übergeben wird.
package main import ( "fmt" "flag" ) var logLevel string func init() { const ( defaultLogLevel = "DEBUG" usage = "set log level value" ) flag.StringVar(&logLevel, "log_type", defaultLogLevel, usage) flag.StringVar(&logLevel, "l", defaultLogLevel, usage + "(shorthand)") } func main() { flag.Parse() fmt.Println("log level:", logLevel) }
Kompilieren und führen Sie das Programm aus:
$ go build -o main main.go $ ./main -log_type WARNING $ ./main -l WARNING
Die Verwendung von langen und kurzen Optionen gibt Folgendes aus:
log level: WARNING
Wenn Sie diese Option nicht übergeben, wird der Standardwert ausgegeben:
$ ./main log level: DEBUG
Parsen von Zeitintervallen
Zusätzlich zur Verwendung von grundlegenden Typen als Optionen unterstützt die flag
-Bibliothek auch den Typ time.Duration
, d.h. Zeitintervalle. Die für Zeitintervalle unterstützten Formate sind sehr vielfältig, z. B. `