Unwrapping mit `errors.Is`
Teil des Abschnitts Logik & Ablauf der GO-Journey von Coddy. Lektion 40 von 68.
Beim Arbeiten mit umschlossenen Fehlern benötigst du eine Möglichkeit zu prüfen, ob ein bestimmter Fehler irgendwo in der Fehlerkette existiert. Die Funktion errors.Is bietet genau diese Möglichkeit und erlaubt es dir, Sentinel-Fehler zu identifizieren, selbst wenn sie mehrfach umschlossen wurden.
Die Funktion errors.Is nimmt zwei Parameter entgegen: den Fehler, den Sie untersuchen möchten, und den Ziel-Fehler, nach dem Sie suchen. Sie gibt true zurück, wenn der Ziel-Fehler irgendwo in der Fehlerkette gefunden wird:
var ErrNotFound = errors.New("not found")
wrappedErr := fmt.Errorf("failed to load user: %w", ErrNotFound)
if errors.Is(wrappedErr, ErrNotFound) {
fmt.Println("This is a not found error")
}Dies ist die moderne, empfohlene Methode, um in Go auf spezifische Fehler zu prüfen. Im Gegensatz zu String-Vergleichen oder direkten Gleichheitsprüfungen funktioniert errors.Is korrekt mit gewrappten Fehlern und folgt der Fehlerkette, um Übereinstimmungen zu finden. Dies macht Ihre Fehlerbehandlung robust und zuverlässig, selbst wenn Fehler mehrere Schichten Ihrer Anwendung durchlaufen.
Aufgabe
EinfachErstelle ein System zur Überwachung von Datenbankverbindungen, das errors.Is verwendet, um bestimmte Verbindungsfehler in verschachtelten Fehlerketten zu identifizieren. Diese Herausforderung zeigt, wie errors.Is verwendet wird, um Sentinel-Fehler zu erkennen, selbst wenn sie über mehrere Anwendungsebenen hinweg mit zusätzlichem Kontext umschlossen wurden.
Du erhältst zwei Eingaben:
- Eine Zeichenkette mit Details zum Datenbankvorgang im Format
"database_name,operation,error_type"(z. B."users_db,connect,connection_timeout") - Eine Zeichenkette mit Anwendungskontext im Format
"service_name,retry_count"(z. B."AuthService,3")
Deine Aufgabe ist:
- Definiere drei Sentinel-Fehler mit
errors.New():ErrConnectionTimeoutmit der Nachricht"connection timeout"ErrConnectionRefusedmit der Nachricht"connection refused"ErrDatabaseNotFoundmit der Nachricht"database not found"
- Analysiere die erste Eingabe, indem du sie an Kommas aufteilst, um Datenbankname, Vorgang und Fehlertyp zu erhalten
- Analysiere die zweite Eingabe, indem du sie an Kommas aufteilst, um Dienstname und Anzahl der Wiederholungsversuche zu erhalten
- Erstelle den ursprünglichen Fehler basierend auf dem Fehlertyp:
- Wenn der Fehlertyp
"connection_timeout"ist: VerwendeErrConnectionTimeout - Wenn der Fehlertyp
"connection_refused"ist: VerwendeErrConnectionRefused - Wenn der Fehlertyp
"database_not_found"ist: VerwendeErrDatabaseNotFound - Für jeden anderen Fehlertyp: Verwende
errors.New("unknown database error")
- Wenn der Fehlertyp
- Erstelle einen umschlossenen Fehler auf Datenbankebene mit
fmt.Errorfund%w:"failed to [operation] database [database_name]: %w" - Erstelle einen umschlossenen Fehler auf Dienstebene:
"[service_name] database operation failed after [retry_count] retries: %w" - Verwende
errors.Is, um zu prüfen, ob der endgültige umschlossene Fehler mit jedem Sentinel-Fehler übereinstimmt, und gib die Ergebnisse aus:"Checking for connection timeout: [true/false]""Checking for connection refused: [true/false]""Checking for database not found: [true/false]"
- Gib die Fehlerkette aus:
"Error Chain:""Original: [original_error_message]""Database level: [database_level_error_message]""Service level: [service_level_error_message]"
- Gib die Fehleranalyse aus:
"Error Analysis:""Database: [database_name]""Operation: [operation]""Service: [service_name]""Retries: [retry_count]""Error type detected: [detected_error_type]", wobei detected_error_type einen der Werte "Connection Timeout", "Connection Refused", "Database Not Found" oder "Unknown Error" enthält
Verwende das Paket strings, um die Eingabezeichenketten an Kommas aufzuteilen, das Paket errors für Sentinel-Fehler und errors.Is sowie das Paket fmt zum Umschließen von Fehlern. Diese Herausforderung zeigt, wie errors.Is eine robuste Fehleridentifikation ermöglicht, die auch mit umschlossenen Fehlern korrekt funktioniert, und dadurch für eine zuverlässige Fehlerbehandlung in komplexen Anwendungen unerlässlich ist.
Probier es selbst
package main
import (
"errors"
"fmt"
"strings"
)
func main() {
// Eingabe lesen
var dbOperation string
var appContext string
fmt.Scanln(&dbOperation)
fmt.Scanln(&appContext)
// Eingaben parsen
dbParts := strings.Split(dbOperation, ",")
databaseName := dbParts[0]
operation := dbParts[1]
errorType := dbParts[2]
contextParts := strings.Split(appContext, ",")
serviceName := contextParts[0]
retryCount := contextParts[1]
// TODO: Schreiben Sie Ihren Code unten
// 1. Definieren Sie die drei Sentinel-Fehler mit errors.New()
// 2. Erstellen Sie den ursprünglichen Fehler basierend auf dem Fehlertyp
// 3. Erstellen Sie einen auf Datenbankebene gewrappten Fehler mit fmt.Errorf und %w
// 4. Erstellen Sie einen auf Serviceebene gewrappten Fehler
// 5. Verwenden Sie errors.Is, um auf jeden Sentinel-Fehler zu prüfen
// 6. Zeigen Sie die Ergebnisse und die Fehlerkette an
}Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Logik & Ablauf
1Fortgeschrittener Kontrollfluss
Switch mit `fallthrough`Abbrechen von verschachtelten SchleifenFortsetzen einer bestimmten SchleifeDie `goto`-AnweisungZusammenfassung – Fortgeschrittene Schleifensteuerung4Projekt: Einfache Aufgabenliste
Projekt-SetupEine Aufgabe hinzufügen7Fehlerbehandlung im Detail
Benutzerdefinierte FehlertypenFehler-Wrapping mit `%w`Unwrapping mit `errors.Is`Unwrapping mit `errors.As``panic` verstehen`recover` verwendenZusammenfassung – Sichere Division2Structs und Methoden
Methoden für Structs definierenValue ReceiverPointer ReceiverReceiver auswählenMethoden vs. FunktionenZusammenfassung – Struct-Verhalten5Maps im Detail
Maps von StructsPointer als Map-WertePrüfen auf Nil-MapsMaps vergleichenZusammenfassung – Wortfrequenz-Zähler8Projekt: Einfache Bestandsverwaltung
ProjektübersichtLagerbestand prüfen11Abschlussherausforderungen
Einfache KontaktlisteEinfacher Zahlen-ValidatorSammler für eindeutige Elemente3Interfaces (Die Grundlagen)
Was ist ein Interface?Ein Interface definierenEin Interface implementierenInterface-Typen verwendenLeeres InterfaceType AssertionsType SwitchZusammenfassung – Formen und VerhaltenÜbe selbstständig: Online-Go-Compiler