Lektionen des Moduls (4/5)
Das Stringer-Interface
fmt.Stringer ist wahrscheinlich die am häufigsten verwendete Standardschnittstelle überhaupt
Gos Standardbibliothek. Es ist die perfekte Demonstration der Macht
von kleinen Schnittstellen.
Definition
type Stringer interface {
String() string
}Eine einzige Signatur. Jeder Typ, der String() string definiert, erfüllt die Anforderungen
es. Und fmt erkennt diese Schnittstelle: wenn Sie einen Wert an übergeben
fmt.Print*, wenn es Stringer implementiert, das Ergebnis von String()
wird anstelle der Standarddarstellung verwendet.
Beispiel
type Point struct{ X, Y int }
func (p Point) String() string {
return fmt.Sprintf("(%d,%d)", p.X, p.Y)
}
fmt.Println(Point{1, 2}) // (1,2)
fmt.Printf("%v %s\n", Point{3, 4}, Point{5, 6})
// (3,4) (5,6)Derselbe Wert wird mit benutzerdefinierter Formatierung in %v, %s, Println gedruckt.
Sprint, log usw. Alles nur durch die Definition einer Methode.
Wenn es Sinn macht
– Typen, die eine Domäne modellieren (IDs, Codes, Koordinaten, Aufzählungen).
- Fehler bei einer für Menschen lesbaren Darstellung (siehe nächste Lektion zu
error). - Typen, die Sie häufig protokollieren und für die Sie ein festes Format wünschen.
Nicht für alles: wenn der Typ einfach ist und die Standarddarstellung ist in Ordnung, kein Rauschen hinzufügen.
Enum-Typen: gemeinsames Muster mit iota
type Status int
const (
OK Status = iota
WARN
ERR
)
func (s Status) String() string {
switch s {
case OK: return "OK"
case WARN: return "WARN"
case ERR: return "ERR"
default: return "UNKNOWN"
}
}
fmt.Println(OK, WARN, ERR) // OK WARN ERROhne String() würde fmt.Println(OK) 0 ausgeben. Mit String(),
es gibt den symbolischen Namen aus. Der stringer
Das Tool generiert dieses Muster automatisch.
Achten Sie auf unendliche Rekursion
type T int
func (t T) String() string {
return fmt.Sprintf("%d", int(t)) // OK: cast to int breaks the recursion
}Stringer auf einem Zeigerempfänger
Wenn String() über einen Zeigerempfänger verfügt, erfüllt nur *T Stringer.
Mit fmt.Println(t) (einem Wert) betrachtet Go den Methodensatz von T,
findet es nicht und verwendet das Standardformat. Um dies zu vermeiden, value
Receiver wird normalerweise für String() verwendet (es ist eine „Ansicht“; das ist nicht der Fall).
etwas ändern).
Probieren Sie es aus
Implementieren Sie String() auf Point, sodass es (X,Y) zurückgibt.
Hinweis anzeigen
Verwenden Sie `fmt.Sprintf`, um die Felder zu formatieren.
Lösung nach 3 Versuchen verfügbar
Implementieren Sie String() für einen Typstatus (int): 0 → „OK“, 1 → „WARN“, andernfalls → „ERR“.
Hinweis anzeigen
Wert des Empfängers einschalten; Denken Sie daran, einen Standardwert anzugeben.
Lösung nach 3 Versuchen verfügbar
Welche Signatur muss die Methode haben, um fmt.Stringer zu erfüllen?
func (x T) ??? {}Zusammenfassung
fmt.Stringer = interface { String() string }. – Die Implementierung ändert die Art und Weise, wiefmt.Print*den Typ darstellt.- Idiomatisch für Enumerationen (
iota), Domänentypen, Codes/Identifikatoren. - Rufen Sie niemals
fmt.Sprintf("%s", t)auftinnerhalb vonString()auf (Rekursion). - Konvention: Wertempfänger für
String()(keine Mutation, vermeidet „Methodensatz-Überraschungen“).