Direkt zum Hauptinhalt springen
eLearner.app
Modul 6 · Lektion 4 von 529/50 im Kurs~10 min
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

Go
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

Go
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

Go
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 ERR

Ohne 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

Go
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

Übung#go.m6.l4.e1
Versuche: 0Wird geladen…

Implementieren Sie String() auf Point, sodass es (X,Y) zurückgibt.

Editor wird geladen…
Hinweis anzeigen

Verwenden Sie `fmt.Sprintf`, um die Felder zu formatieren.

Lösung nach 3 Versuchen verfügbar

Übung#go.m6.l4.e2
Versuche: 0Wird geladen…

Implementieren Sie String() für einen Typstatus (int): 0 → „OK“, 1 → „WARN“, andernfalls → „ERR“.

Editor wird geladen…
Hinweis anzeigen

Wert des Empfängers einschalten; Denken Sie daran, einen Standardwert anzugeben.

Lösung nach 3 Versuchen verfügbar

Quiz#go.m6.l4.e3
Bereit

Welche Signatur muss die Methode haben, um fmt.Stringer zu erfüllen?

Go
func (x T) ??? {}
Antwortoptionen

Zusammenfassung

  • fmt.Stringer = interface { String() string }. – Die Implementierung ändert die Art und Weise, wie fmt.Print* den Typ darstellt.
  • Idiomatisch für Enumerationen (iota), Domänentypen, Codes/Identifikatoren.
  • Rufen Sie niemals fmt.Sprintf("%s", t) auf t innerhalb von String() auf (Rekursion).
  • Konvention: Wertempfänger für String() (keine Mutation, vermeidet „Methodensatz-Überraschungen“).