Modulelessen (4/5)
De Stringer-interface
fmt.Stringer is waarschijnlijk de meest gebruikte standaardinterface van allemaal
Go's standaardbibliotheek. Het is de perfecte demonstratie van de kracht
van kleine interfaces.
Definitie
type Stringer interface {
String() string
}Eén enkele handtekening. Elk type dat String() string definieert, voldoet
het. En fmt herkent deze interface: wanneer u een waarde doorgeeft aan
fmt.Print*, als Stringer wordt geïmplementeerd, het resultaat van String()
wordt gebruikt in plaats van de standaardweergave.
Voorbeeld
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)Dezelfde waarde wordt afgedrukt met aangepaste opmaak in %v, %s, Println,
Sprint, log, enz. Allemaal door slechts één methode te definiëren.
Wanneer het zinvol is
- Typen die een domein modelleren (ids, codes, coördinaten, opsommingen).
- Fouten met een voor mensen leesbare weergave (zie volgende les over
error). - Typen die u vaak logt en waarvoor u een vast formaat wilt.
Niet voor alles: als het type eenvoudig is en de standaardweergave is prima, voeg geen ruis toe.
Enum-typen: algemeen patroon met 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 ERRZonder String() zou fmt.Println(OK) 0 afdrukken. Met String(),
het drukt de symbolische naam af. De stringer
tool genereert dit patroon automatisch.
Pas op voor oneindige recursie
type T int
func (t T) String() string {
return fmt.Sprintf("%d", int(t)) // OK: cast to int breaks the recursion
}Stringer op een aanwijzerontvanger
Als String() een pointerontvanger heeft, voldoet alleen *T aan Stringer.
Met fmt.Println(t) (een waarde) kijkt Go naar de methodenset van T,
kan het niet vinden en gebruikt het standaardformaat. Om dit te voorkomen, gebruikt u value
ontvanger wordt meestal gebruikt voor String() (het is een "weergave"; dat is niet het geval
iets aanpassen).
Probeer het
Implementeer String() op Point zodat het (X,Y) retourneert.
Toon hint
Gebruik `fmt.Sprintf` om de velden op te maken.
Oplossing beschikbaar na 3 pogingen
Implementeer String() op een type Status (int): 0 → 'OK', 1 → 'WARN', anders → 'ERR'.
Toon hint
Schakel de waarde van de ontvanger in; Vergeet niet een standaardinstelling op te geven.
Oplossing beschikbaar na 3 pogingen
Welke handtekening moet de methode hebben om aan fmt.Stringer te voldoen?
func (x T) ??? {}Samenvatten
fmt.Stringer = interface { String() string }.- Door het te implementeren verandert de manier waarop
fmt.Print*het type vertegenwoordigt. - Idiomatisch voor enums (
iota), domeintypen, codes/identifiers. - Bel nooit
fmt.Sprintf("%s", t)optbinnenString()(recursie). - Conventie: waardeontvanger voor
String()(geen mutatie, vermijdt "methode-set verrassingen").