fmt.Stringer Interface
Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy — Lektion 75 von 107.
Das fmt.Stringer-Interface steuert, wie Ihre Typen bei der Ausgabe dargestellt werden. Es ist eines der am häufigsten implementierten Interfaces in Go und wird im fmt-Paket definiert:
type Stringer interface {
String() string
}Wenn Sie einen Wert an fmt.Println, fmt.Printf mit %v oder ähnliche Funktionen übergeben, prüft Go, ob der Typ Stringer implementiert. Falls dies der Fall ist, ruft Go die String()-Methode auf, um die Textdarstellung zu erhalten.
type Temperature struct {
Celsius float64
}
func (t Temperature) String() string {
return fmt.Sprintf("%.1f°C", t.Celsius)
}
func main() {
temp := Temperature{Celsius: 23.5}
fmt.Println(temp) // 23.5°C
}Ohne die String()-Methode würde die Ausgabe das Standard-Struct-Format anzeigen: {23.5}. Durch die Implementierung von Stringer steuern Sie genau, wie sich Ihr Typ darstellt.
Dies ist besonders nützlich für Typen, bei denen die rohen Feldwerte die Bedeutung nicht klar vermitteln. Ein Duration-Typ könnte als „2h 30m“ angezeigt werden, anstatt rohe Nanosekunden anzuzeigen, oder ein User-Typ könnte einen formatierten Namen anstelle all seiner Felder anzeigen.
Aufgabe
EinfachLassen Sie uns ein Zeiterfassungssystem bauen, das Zeitdauern in einem benutzerfreundlichen Format anzeigt! Sie werden das fmt.Stringer-Interface implementieren, um zu steuern, wie Ihre benutzerdefinierten Typen beim Drucken erscheinen.
Sie werden Ihren Code auf zwei Dateien aufteilen:
duration.go: Definieren Sie Ihre zeitbezogenen Typen mit benutzerdefinierten String-Repräsentationen.Erstellen Sie ein
Duration-Struct, das eine Gesamtzahl von Minuten als Ganzzahl speichert. Implementieren Sie dieString()-Methode so, dass sie beim Drucken in einem lesbaren Format wie2h 30mfür 150 Minuten oder0h 45mfür 45 Minuten angezeigt wird. Stunden und Minuten sollten immer angezeigt werden.Erstellen Sie ein
Task-Struct mit Feldern fürName(String) undTime(Duration). Implementieren SieString()für Task, um es im Format[Name]: [duration]anzuzeigen, wobei die Dauer ihre eigene String-Methode verwendet.main.go: Erstellen und Anzeigen von Aufgaben mit ihren Zeitdauern.Lesen Sie eine Anzahl von Aufgaben ein, und lesen Sie dann für jede Aufgabe ihren Namen und die Dauer in Minuten. Erstellen Sie Task-Instanzen und drucken Sie jede einzelne direkt mit
fmt.Printlnaus – das Stringer-Interface übernimmt die Formatierung automatisch.Nachdem Sie alle Aufgaben gedruckt haben, berechnen und drucken Sie die Gesamtzeit aller Aufgaben im Format:
Total: [duration]
Die folgenden Eingaben werden bereitgestellt:
- Zeile 1: Anzahl der Aufgaben
- Folgende Zeilen: Aufgabenname und Minuten (zwei Zeilen pro Aufgabe)
Zum Beispiel, gegeben:
3
Code Review
90
Meeting
45
Documentation
120Ihre Ausgabe sollte sein:
Code Review: 1h 30m
Meeting: 0h 45m
Documentation: 2h 0m
Total: 4h 15mUnd gegeben:
2
Design
180
Testing
65Ihre Ausgabe sollte sein:
Design: 3h 0m
Testing: 1h 5m
Total: 4h 5mDurch die Implementierung von Stringer lassen sich Ihre Typen nahtlos in die Druckfunktionen von Go integrieren. Anstatt rohe Struct-Felder wie {90} zu sehen, erhalten Sie eine aussagekräftige Ausgabe, die für Benutzer sinnvoll ist.
Spickzettel
Das fmt.Stringer-Interface steuert, wie Typen beim Drucken erscheinen:
type Stringer interface {
String() string
}Wenn Sie einen Wert an fmt.Println oder fmt.Printf mit %v übergeben, prüft Go, ob der Typ Stringer implementiert. Falls ja, ruft Go die Methode String() auf, um die Textdarstellung zu erhalten.
Beispiel-Implementierung:
type Temperature struct {
Celsius float64
}
func (t Temperature) String() string {
return fmt.Sprintf("%.1f°C", t.Celsius)
}
func main() {
temp := Temperature{Celsius: 23.5}
fmt.Println(temp) // 23.5°C
}Ohne die Methode String() zeigt die Ausgabe das Standardformat für Structs: {23.5}. Durch die Implementierung von Stringer steuern Sie genau, wie sich Ihr Typ präsentiert, wodurch die Ausgabe aussagekräftiger und benutzerfreundlicher wird.
Probier es selbst
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Anzahl der Aufgaben lesen
line, _ := reader.ReadString('\n')
numTasks, _ := strconv.Atoi(strings.TrimSpace(line))
// TODO: Erstelle ein Slice, um Aufgaben zu speichern
// TODO: Verfolge die Gesamtzahl der Minuten
for i := 0; i < numTasks; i++ {
// Aufgabennamen lesen
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
// Aufgabendauer in Minuten lesen
minutesLine, _ := reader.ReadString('\n')
minutes, _ := strconv.Atoi(strings.TrimSpace(minutesLine))
// TODO: Erstelle eine Aufgabe (Task) mit dem Namen und der Dauer (Duration)
// TODO: Gib die Aufgabe aus (fmt.Println wird das Stringer-Interface verwenden)
// TODO: Minuten zur Gesamtsumme hinzufügen
_ = name
_ = minutes
}
// TODO: Gib die Gesamtdauer im Format "Total: Xh Ym" aus
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der Go OOP
Externe DateienGo Workspace & ModulePackages & ImportsExportierte vs. nicht-exportierte NamenEinführung in OOP in GoStructs als KlassenMethoden für Structs definierenPointer- vs. Value-ReceiverStruct-InitialisierungKonstruktor-FunktionenZusammenfassung – Einfacher Taschenrechner4Interfaces
Einführung in InterfacesImplizite ImplementierungInterface als VertragLeeres Interface (any)Type AssertionType SwitchInterface-KompositionStringer & Error InterfacesRückblick - Formen-Rechner7Kapselung
Exportierte vs. nicht exportierte FelderKapselung auf Paket-EbeneGetter- & Setter-MethodenInformation Hiding in GoZusammenfassung - Studierendendatensätze10Generics (Go 1.18+)
Einführung in GenericsTypparameterType ConstraintsGenerische StructsWorkaround für generische MethodenZusammenfassung – Generische Collection2Vertiefung: Typen & Structs
Basis- & zusammengesetzte TypenBenutzerdefinierte TypdefinitionenStruct TagsAnonyme StructsVerschachtelte StructsZero Values & StandardwerteZusammenfassung - Kontaktbuch5Komposition statt Vererbung
Warum Go keine Vererbung hatGrundlagen des Struct EmbeddingMethod PromotionEinbetten mehrerer StructsEmbedding vs. AggregationShadowing eingebetteter MethodenZusammenfassung – Mitarbeiter-Hierarchie8Fehlerbehandlung & OOP
Das error-InterfaceEigene FehlertypenError Wrapping (fmt.Errorf)Sentinel-Fehlererrors.Is() und errors.As()Panic, Defer und RecoverZusammenfassung – Datei-Parser11Standardbibliothek & OOP
io.Reader & io.Writersort.Interfacefmt.Stringer Interfaceencoding/json mit Structshttp.Handler InterfaceZusammenfassung - REST-API-Modelle3Zeiger & Speicher
Zeiger-Grundlagen in GoZeiger auf StructsWertübergabe vs. ReferenzübergabeDie new() FunktionGarbage Collection in GoWiederholung – Linked List Builder6Polymorphismus in Go
Polymorphismus über InterfacesDuck Typing in GoInterface-ErfüllungsregelnPolymorphe CollectionsDependency InjectionZusammenfassung – Payment Processor9Nebenläufigkeit & OOP
Goroutines GrundlagenChannels & KommunikationGepufferte vs. ungepufferte ChannelsSelect-Anweisungsync.Mutex & sync.RWMutexsync.WaitGroupThread-sicheres Struct-DesignZusammenfassung - Worker Pool