Stringer & Error Interfaces
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 fmt-Package 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
EinfachLassen Sie uns ein Temperaturüberwachungssystem bauen, das sowohl das Stringer- als auch das error-Interface verwendet, um lesbare Ausgaben und eine aussagekräftige Fehlerbehandlung zu ermöglichen.
Sie werden Ihren Code auf zwei Dateien aufteilen:
temperature.go: Erstellen Sie einTemperature-Struct mit den FeldernValue(float64) undUnit(string). Implementieren Sie dieString()-Methode so, dass sie bei der Ausgabe die Temperatur in einem menschenlesbaren Format anzeigt. Erstellen Sie außerdem einTemperatureError-Struct mit den FeldernTemp(float64) undReason(string) und implementieren Sie dieError()-Methode, um beschreibende Fehlermeldungen bereitzustellen.main.go: Erstellen Sie 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. Lesen Sie Temperaturdaten aus der Eingabe ein, erstellen Sie eine Temperature, validieren Sie diese und geben Sie die entsprechende Ausgabe aus.
Die folgenden Eingaben werden bereitgestellt:
- Zeile 1: Temperaturwert (float)
- Zeile 2: Einheit (
Cfür Celsius oderFfür Fahrenheit)
Ihre String()-Methode sollte folgendes Format zurückgeben:
[Value] degrees [Unit]Wobei Unit das vollständige Wort "Celsius" oder "Fahrenheit" basierend auf der Eingabe ist.
Ihre Error()-Methode sollte folgendes Format zurückgeben:
invalid temperature [Temp]: [Reason]Wenn die Temperatur gültig ist, geben Sie die Temperature mit fmt.Println aus (was Ihre String()-Methode verwenden wird). Wenn sie ungültig ist, geben Sie den Fehler aus (was Ihre Error()-Methode verwenden wird).
Zum Beispiel sollte bei 25.5 und C Ihre Ausgabe wie folgt aussehen:
25.5 degrees CelsiusBei -500 und F sollte Ihre Ausgabe wie folgt aussehen:
invalid temperature -500: below absolute zeroVerwenden Sie "below absolute zero" als Grund (Reason), wenn die Temperatur zu niedrig ist.
Spickzettel
Die Standardbibliothek von Go definiert zwei wesentliche Schnittstellen: fmt.Stringer und error.
Die Stringer-Schnittstelle
Die Stringer-Schnittstelle aus dem fmt-Paket erfordert eine Methode:
type Stringer interface {
String() string
}Wenn Sie String() für Ihren Typ implementieren, verwenden Funktionen wie fmt.Println diese automatisch:
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 years old)
}Die error-Schnittstelle
Die error-Schnittstelle erfordert eine Error()-Methode, die einen String zurückgibt:
type error interface {
Error() string
}Jeder Typ mit einer Error()-Methode kann als Fehlerwert verwendet werden, was benutzerdefinierte Fehlertypen mit zusätzlichem Kontext ermöglicht:
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
}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 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-Parser3Zeiger & 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