Lektionen des Moduls (1/5)
Fortgeschrittenes `fmt`
Das fmt-Paket ist das Gateway zu allen textuellen E/A in Go. Wenn Sie es gut kennen, müssen Sie lesbare Protokolle schreiben, Fehler melden und Werte idiomatisch formatieren, ohne auf externe Bibliotheken zurückgreifen zu müssen.
Die vier Familien
fmt stellt Funktionen in vier Familien bereit, die durch das Präfix unterschieden werden:
Print*→ schreibt nachos.Stdout(Print,Println,Printf).Fprint*→ schreibt in einen beliebigenio.Writer(Fprintln(os.Stderr, ...),Fprintf(file, ...)).Sprint*→ gibt einen String ohne Ausdruck zurück (os.Stdout0,os.Stdout1).os.Stdout2 → erstellt einen formatiertenos.Stdout3.
fmt.Println("hello") // stdout
fmt.Fprintln(os.Stderr, "boom") // stderr
s := fmt.Sprintf("[%d]", 42) // "[42]"
err := fmt.Errorf("parse %q: %w", in, base) // wrapped errorDer Unterschied zwischen Print und Println besteht nur im Leerzeichen zwischen den Argumenten und dem abschließenden Zeilenumbruch: Println fügt immer hinzu, Print nicht, Printf folgt dem Format.
Hauptverben
| Verb | Was es tut |
|---|---|
%v | Standardwert (ruft String() auf, falls implementiert). |
%+v | Struktur mit Feldnamen. |
%#v | Go-Syntax (nützlich für Debugging und Snapshots). |
%T | Dynamischer Typ des Werts. |
%d | Ganzzahl zur Basis 10. |
%b %o %x %X | Binär, oktal, hexadezimal (Klein-/Großbuchstaben). |
%f %e %g | Gleitkomma: fest, exponentiell, kompakt. |
%s | Zeichenfolge (oder error/String()0). |
String()1 | Anführungszeichen-String im Go-Stil (einschließlich Escapezeichen). |
String()2 | Unicode-Zeichen (String()3). |
String()4 | Zeiger im Hexadezimalformat. |
String()5 | Fehlerumbruch (nur innerhalb von String()6). |
type Point struct{ X, Y int }
p := Point{1, 2}
fmt.Printf("%v\n", p) // {1 2}
fmt.Printf("%+v\n", p) // {X:1 Y:2}
fmt.Printf("%#v\n", p) // main.Point{X:1, Y:2}
fmt.Printf("%T\n", p) // main.PointBreite, Präzision, Flags
Numerische und String-Verben akzeptieren Breite und Genauigkeit:
%6d→ Mindestbreite 6, links mit Leerzeichen auffüllen.%-6d→ Breite 6, rechter Abstand (Flag-).%06d→ Breite 6, Auffüllen mit0(Flag0).%.2f→ Genauigkeit 2 Dezimalstellen.%8.2f→ Breite 8, Genauigkeit 2.
fmt.Printf("|%6d|\n", 42) // | 42|
fmt.Printf("|%-6d|\n", 42) // |42 |
fmt.Printf("|%06d|\n", 42) // |000042|
fmt.Printf("|%8.2f|\n", 3.14)// | 3.14|Bei ausgerichteten Tabellen ist feste Breite + %-...s für Textspalten das einfachste Muster vor dem Wechsel zu text/tabwriter.
%w und Fehlerumbruch
%w ist etwas Besonderes: Es funktioniert nur innerhalb von fmt.Errorf und behält den ursprünglichen Fehler in der Kette bei, sodass errors.Is und errors.As ihn durchlaufen können.
if _, err := os.Open(path); err != nil {
return fmt.Errorf("read config %q: %w", path, err)
}Die Verwendung von %v anstelle von %w gibt die Fehlermeldung aus, unterbricht jedoch die Kette: kein Entpacken, kein errors.Is. Regel: Wenn Sie möchten, dass der Anrufer die Art oder Identität des Fehlers erkennen kann, verwenden Sie %w (nur einen pro Errorf).
Übungen
Verwenden Sie fmt.Sprintf, um die Zeichenfolge „[42]“ aus der Ganzzahl 42 zu formatieren, und drucken Sie sie dann aus.
Lösung nach 3 Versuchen verfügbar
Geben Sie die Struktur p mit dem Verb %+v aus (sie muss die Feldnamen enthalten).
Lösung nach 3 Versuchen verfügbar
Welches Verb, das in fmt.Errorf verwendet wird, bewahrt die Fehlerkette fürerrors.Is/As?
err := fmt.Errorf("read %q: ???", path, base)