Das fmt-Paket bündelt Gos formatierte Ein- und Ausgabe: vom schnellen Println im Hello-World bis zum produktionsreifen Error-Wrapping mit %w. Es ist eines der ersten Pakete, das jeder Go-Entwickler kennenlernt — und gleichzeitig eines der am häufigsten unterschätzten. Wer die Format-Verben beherrscht, das Stringer-Interface implementiert und Errorf mit %w korrekt einsetzt, schreibt Code, der sich später wie selbsterklärendes Englisch liest.
Dieser Bereich ist als Referenz aufgebaut: Die Übersicht erklärt die drei Funktionsfamilien und ihre gemeinsamen Konzepte, jede einzelne Funktion und jeder Typ haben eine eigene Detail-Seite mit Signatur, ausführlicher Erklärung, Beispielen und Stolperfallen. Wer das Paket zum ersten Mal lernt, liest hier von oben nach unten. Wer eine konkrete Funktion nachschlagen will, springt direkt zur passenden Seite. Offizielle Referenz: pkg.go.dev/fmt.
Drei Funktionsfamilien plus Errorf
Die zwölf Print-Funktionen ergeben sich aus drei orthogonalen Dimensionen: Ziel (Stdout, Writer, String), Format (positional vs. Format-String) und Newline-Verhalten. Diese systematische Komposition macht das API auf den ersten Blick sperrig, aber sobald man das Muster verinnerlicht hat, leitet man jede Variante aus dem Namen ab.
| Familie | Ziel | Beispiel |
|---|---|---|
os.Stdout | fmt.Println("hi") | |
| Fprint | io.Writer | fmt.Fprintln(os.Stderr, "err") |
| Sprint | string | s := fmt.Sprintf("%d", n) |
| Append (Go 1.19+) | []byte | buf = fmt.Appendf(buf, "%d", n) |
| Errorf | error | return fmt.Errorf("op: %w", err) |
| Scan | von Stdin/Reader/String | fmt.Sscanf(s, "%d", &n) |
Innerhalb jeder Familie gibt es drei Newline-Varianten: ohne Suffix (positional, kein Newline), mit ln-Suffix (positional, Newline am Ende), mit f-Suffix (Format-String, kein Newline). Die einzige Ausnahme ist Errorf, das per Konvention keinen Newline anhängt — Errors sollen ohne \n enden, weil Logger und Wrapper sich selbst um die Zeilentrennung kümmern.
Format-Verben — der Kern des Pakets
Die Format-Verben sind das Herzstück von Printf und Verwandten. Jedes Verb gehört zu einer Typklasse: generelle Verben wirken auf jeden Wert, Integer-Verben nur auf Ganzzahlen, Float-Verben nur auf Fließkommazahlen, String-Verben auf Strings und Byte-Slices. Die Auswahl ist überschaubar, aber sehr ausdrucksstark, sobald man sie auswendig kennt.
Die wichtigsten Verben in einem Satz: %v für die Default-Darstellung, %+v für Structs mit Feldnamen, %#v für die Go-Syntax-Repräsentation, %T für den konkreten Typ, %d für Dezimal-Integer, %x für Hex, %f für Floats, %s für Strings, %q für gequotete Strings, %w für Error-Wrapping, %t für Booleans, %c für Runes, %p für Pointer. Eine vollständige Tabelle mit allen Verben und Modifikatoren findet sich auf der eigenen Format-Verben-Seite.
Custom-Formatierung über Interfaces
fmt ruft beim Formatieren automatisch passende Interface-Methoden auf, sofern der Wert sie implementiert. Das macht eigene Typen integrierbar, ohne dass Aufrufer wissen müssen, wie sie zu formatieren sind. Drei Interfaces sind dafür relevant:
fmt.Stringer— dieString() string-Methode. Wird von%s,%v,%qautomatisch genutzt. Standardlösung für lesbare Repräsentation von Custom-Typen.fmt.GoStringer— dieGoString() string-Methode. Wird nur von%#vgenutzt. Selten implementiert, aber nützlich für Bug-Reports und Code-Generation.fmt.Formatter— die volle Kontrolle:Format(f State, verb rune). Erlaubt verb-spezifische Formatierung, etwa unterschiedliche Repräsentation für%vvs.%svs.%q. Implementiert vontime.Time,big.Intund ähnlichen Typen.
Die meisten Anwendungen brauchen nur Stringer. Formatter wird interessant, wenn ein Typ mehrere natürliche Darstellungen hat — eine kompakte für Logs, eine ausführliche für Debug-Output.
Funktionen — Print-Familie (zu Stdout)
Die Print-Familie schreibt direkt nach os.Stdout. Sie ist die Standardwahl für CLI-Output und schnelles Debugging.
fmt.Print— positional, kein Newline. Argumente werden mit Leerzeichen getrennt, wenn keines davon ein String ist.fmt.Println— positional, Newline am Ende. Argumente immer mit Leerzeichen getrennt.fmt.Printf— Format-String mit Verben, kein Newline. Die wichtigste Funktion des ganzen Pakets.
Funktionen — Fprint-Familie (zu io.Writer)
Die Fprint-Familie schreibt auf einen beliebigen io.Writer — eine Datei, ein Netzwerk-Socket, ein bytes.Buffer, os.Stderr. Identisches Verhalten wie Print, nur das Ziel ist explizit.
fmt.Fprint— positional, kein Newline.fmt.Fprintln— positional, Newline am Ende.fmt.Fprintf— Format-String, kein Newline. Standardwahl für strukturiertes Schreiben in Logs und HTTP-Responses.
Funktionen — Sprint-Familie (zu String)
Die Sprint-Familie liefert das Ergebnis als string zurück, ohne irgendwohin zu schreiben. Praktisch für String-Konstruktion, Logging-Pipelines und alles, was den Wert weiterverarbeitet.
fmt.Sprint— positional, kein Newline, liefert string.fmt.Sprintln— positional, Newline am Ende, liefert string.fmt.Sprintf— Format-String, liefert string. Die meistgenutzte Funktion des Pakets neben Printf.
Funktionen — Append-Familie (Go 1.19+)
Die Append-Familie schreibt formatierte Daten in einen vorhandenen []byte-Slice. Praktisch für Hot-Paths, in denen man Allokationen vermeiden möchte — der Slice wird wiederverwendet, kein neuer String entsteht.
fmt.Append— positional, kein Newline, schreibt in []byte.fmt.Appendln— positional, Newline.fmt.Appendf— Format-String.
Funktion — Error-Wrapping
fmt.Errorf— Format-String, lieferterror. Mit dem%w-Verb der idiomatische Weg, Errors zu wrappen.
Funktionen — Scan-Familie
Die Scan-Familie parst Eingaben statt zu schreiben. In der Praxis selten genutzt — für ernsthaftes Parsing ist bufio.Scanner plus strconv deutlich robuster, weil Scan-Funktionen empfindlich auf Whitespace und Encoding reagieren. Trotzdem nützlich für simple Format-Konvertierungen.
fmt.Scan— liest vonos.Stdin, positional.fmt.Scanln— wie Scan, stoppt am Newline.fmt.Scanf— Format-String von Stdin.fmt.Sscan— liest aus einem String.fmt.Sscanln— aus String, stoppt am Newline.fmt.Sscanf— aus String, Format-String.fmt.Fscan— liest ausio.Reader.fmt.Fscanln— aus Reader, stoppt am Newline.fmt.Fscanf— aus Reader, Format-String.
Konzepte und Referenz
Diese Seiten erklären Querschnittsthemen, die mehrere Funktionen gleichzeitig betreffen.
- Format-Verben — vollständige Referenz — Tabelle aller Verben mit Beispielen, Typklassen-Zuordnung und Auswahl-Faustregeln.
- Width, Precision, Flags — Modifikatoren zwischen
%und dem Verb:%-10.2f,%05d,%+d,%#x, dynamische Breite mit%*d. - %v vs %+v vs %#v im Vergleich — Die drei Debug-Verben am gleichen Wert. Wann welches Verb.
- Error-Wrapping mit %w —
fmt.Errorfmit dem Wrap-Verb,errors.Is/errors.As-Interop, mehrfaches%wab Go 1.20. - Stringer, GoStringer, Formatter — welches Interface wann? — Entscheidungsleitfaden zwischen den drei Output-Interfaces, Reihenfolge der Hook-Auswertung, typische Anti-Pattern.
- Scan-Familie vs. bufio.Scanner — Wann fmt.Scan ausreicht und wann bufio.Scanner+strconv die robustere Wahl ist; mit Migrations-Pfad.
- Print, Fprint, Sprint, Append im Vergleich — Die vier Output-Familien an einer Stelle: Senken, Allokation, Testbarkeit, Hot-Path-Tauglichkeit.
- fmt-Performance — wann allokiert es, wann nicht? — Allokations-Quellen, Reflection-Kosten, strconv vs. fmt für Zahlen, Append-Familie als Hot-Path.
Typen und Interfaces
fmt.Stringer—String() string. Das mit Abstand wichtigste Interface des Pakets.fmt.GoStringer—GoString() stringfür%#v.fmt.Formatter—Format(f State, verb rune). Volle Kontrolle pro Verb.fmt.Scanner— eigene Parse-Logik für die Scan-Familie. Spiegel zuFormatter.fmt.ScanState— der Eingabe-Kontext fürScanner.ScanmitToken,SkipSpace,Width.fmt.State— der Kontext, denFormatter.Formatzur Laufzeit bekommt: Breite, Präzision, Flags, Writer.
Weiterführende Ressourcen
Externe Quellen
fmt— Go Documentation- Effective Go: Printing
- Go Blog: Working with Errors in Go 1.13
StringerInterfaceerrors.Is,errors.As,errors.Unwrap