Stringer- und Error-Schnittstellen
Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy. Lektion 32 von 107.
Gos Standardbibliothek definiert zwei Schnittstellen, die Sie ständig verwenden werden: fmt.Stringer und error. Beide sind einfache Ein-Methoden-Schnittstellen, die Ihren Typen eine leistungsstarke Integration mit der integrierten Funktionalität von Go ermöglichen.
Das Stringer-Interface befindet sich im Paket fmt und erfordert nur eine Methode:
type Stringer interface {
String() string
}Wenn Sie String() für Ihren Typ implementieren, verwenden Funktionen wie fmt.Println diese automatisch, um Ihren Wert anzuzeigen:
type Person struct {
Name string
Age int
}
func (p Person) String() string {
return fmt.Sprintf("%s (%d years old)", p.Name, p.Age)
}
func main() {
p := Person{Name: "Alice", Age: 30}
fmt.Println(p) // Alice (30 Jahre alt)
}Das error-Interface ist ebenso einfach und erfordert eine Error()-Methode, die einen String zurückgibt:
type error interface {
Error() string
}Jeder Typ mit einer Error()-Methode kann in Go als Fehlerwert verwendet werden. Dies ermöglicht es Ihnen, benutzerdefinierte Fehlertypen mit zusätzlichem Kontext zu erstellen:
type ValidationError struct {
Field string
Message string
}
func (e ValidationError) Error() string {
return fmt.Sprintf("%s: %s", e.Field, e.Message)
}
func main() {
err := ValidationError{Field: "email", Message: "invalid format"}
fmt.Println(err) // email: invalid format
}Diese beiden Interfaces demonstrieren die Philosophie von Go: kleine, fokussierte Interfaces, die durch implizite Implementierung mächtiges Verhalten ermöglichen.
Aufgabe
EinfachErstellen wir ein Temperaturüberwachungssystem, das sowohl die Schnittstellen Stringer als auch error verwendet, um eine lesbare Ausgabe und eine aussagekräftige Fehlerbehandlung bereitzustellen.
Du organisierst deinen Code über zwei Dateien:
temperature.go: Erstelle eineTemperature-Struktur mit den FeldernValue(float64) undUnit(string). Implementiere die MethodeString(), sodass beim Ausgeben die Temperatur in einem für Menschen lesbaren Format angezeigt wird. Erstelle außerdem eineTemperatureError-Struktur mit den FeldernTemp(float64) undReason(string), und implementiere die MethodeError(), um beschreibende Fehlermeldungen bereitzustellen.main.go: Erstelle eine Funktion namensValidateTemperature, die eineTemperatureentgegennimmt und einen Fehler zurückgibt, wenn die Temperatur ungültig ist. Eine Temperatur ist ungültig, wenn sie unter dem absoluten Nullpunkt liegt (-273.15 für Celsius, -459.67 für Fahrenheit). Wenn sie gültig ist, gibt die Funktionnilzurück. Lies Temperaturdaten aus der Eingabe ein, erstelle eine Temperature, überprüfe sie und gib eine entsprechende Ausgabe aus.
Die folgenden Eingaben werden bereitgestellt:
- Zeile 1: Temperaturwert (float)
- Zeile 2: Einheit (
Cfür Celsius oderFfür Fahrenheit)
Deine Methode String() sollte folgendes Format zurückgeben:
[Value] degrees [Unit]Wobei Unit abhängig von der Eingabe das vollständige Wort "Celsius" oder "Fahrenheit" ist.
Deine Methode Error() sollte folgendes Format zurückgeben:
invalid temperature [Temp]: [Reason]Wenn die Temperatur gültig ist, gib die Temperature mit fmt.Println aus (dabei wird deine Methode String() verwendet). Wenn sie ungültig ist, gib den Fehler aus (dabei wird deine Methode Error() verwendet).
Wenn beispielsweise 25.5 und C gegeben sind, sollte deine Ausgabe folgendermaßen aussehen:
25.5 degrees CelsiusWenn -500 und F gegeben sind, sollte deine Ausgabe folgendermaßen aussehen:
invalid temperature -500: below absolute zeroVerwende "below absolute zero" als Grund, wenn die Temperatur zu niedrig ist.
Probier es selbst
package main
import (
"fmt"
)
// ValidateTemperature prüft, ob eine Temperatur gültig ist
// Gibt einen Fehler zurück, wenn die Temperatur unter dem absoluten Nullpunkt liegt
// Absoluter Nullpunkt: -273.15 für Celsius, -459.67 für Fahrenheit
func ValidateTemperature(t Temperature) error {
// TODO: Validierungslogik implementieren
// Prüfen, ob die Temperatur basierend auf der Einheit unter dem absoluten Nullpunkt liegt
// Gibt einen TemperatureError zurück, wenn ungültig, nil, wenn gültig
return nil
}
func main() {
var value float64
var unit string
fmt.Scanln(&value)
fmt.Scanln(&unit)
// TODO: Erstelle ein Temperature struct mit den Eingabewerten
// TODO: Validiere die Temperatur mit ValidateTemperature
// TODO: Wenn ein Fehler auftritt, gib den Fehler aus
// Andernfalls gib die Temperatur aus (was die String() Methode verwendet)
}
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 OOP in Go
Externe DateienGo-Workspace & ModulePackages & ImportsExportierte vs. nicht exportierte NamenEinführung in OOP mit GoStructs als KlassenMethoden für Structs definierenPointer- vs. Value-ReceiverStruct-InitialisierungKonstruktorfunktionenRückblick – Einfacher Taschenrechner4Schnittstellen
Einführung in SchnittstellenImplizite ImplementierungSchnittstelle als VertragLeere Schnittstelle (any)TypzusicherungTypwechselZusammensetzung von SchnittstellenStringer- und Error-SchnittstellenRückblick – Formenrechner7Kapselung
Exportierte vs. nicht exportierte FelderKapselung auf PaketebeneGetter- und Setter-MethodenInformationsverbergung in GoRückblick – Studierendendatensätze10Generics (Go 1.18+)
Einführung in GenericsTypparameterTypbeschränkungenGenerische StrukturenWorkaround für generische MethodenZusammenfassung – Generische Sammlung2Typen & Structs im Detail
Grundlegende & zusammengesetzte TypenBenutzerdefinierte TypdefinitionenStruct-TagsAnonyme StructsVerschachtelte StructsNullwerte & StandardwerteRückblick – Kontaktbuch5Komposition statt Vererbung
Warum Go keine Vererbung hatGrundlagen der Struct-EinbettungMethoden-PromotionMehrere Structs einbettenEinbettung vs. AggregationVerbergen eingebetteter MethodenRückblick – Mitarbeiterhierarchie8Fehlerbehandlung & OOP
Das Error-InterfaceBenutzerdefinierte FehlertypenError-Wrapping (fmt.Errorf)Sentinel-Fehlererrors.Is() und errors.As()Panic, Defer und RecoverRückblick – Dateiparser3Zeiger & Speicher
Grundlagen von Zeigern in GoZeiger auf StructsÜbergabe per Wert vs. ReferenzDie Funktion new()Garbage Collection in GoRückblick – Verkettete Liste erstellen6Polymorphismus in Go
Polymorphismus über InterfacesDuck-Typing in GoRegeln zur Interface-ErfüllungPolymorphe SammlungenDependency InjectionZusammenfassung – Zahlungsprozessor9Konkurrenz & OOP
Grundlagen der GoroutinesChannels & KommunikationGepufferte vs. ungepufferte ChannelsSelect-Anweisungsync.Mutex & sync.RWMutexsync.WaitGroupThread-sicheres Struct-DesignRückblick – Worker PoolÜbe selbstständig: Online-Go-Compiler