Menu
Coddy logo textTech

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.

challenge icon

Aufgabe

Einfach

Erstelle 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:

  1. Definiere drei Sentinel-Fehler mit errors.New():
    • ErrConnectionTimeout mit der Nachricht "connection timeout"
    • ErrConnectionRefused mit der Nachricht "connection refused"
    • ErrDatabaseNotFound mit der Nachricht "database not found"
  2. Analysiere die erste Eingabe, indem du sie an Kommas aufteilst, um Datenbankname, Vorgang und Fehlertyp zu erhalten
  3. Analysiere die zweite Eingabe, indem du sie an Kommas aufteilst, um Dienstname und Anzahl der Wiederholungsversuche zu erhalten
  4. Erstelle den ursprünglichen Fehler basierend auf dem Fehlertyp:
    • Wenn der Fehlertyp "connection_timeout" ist: Verwende ErrConnectionTimeout
    • Wenn der Fehlertyp "connection_refused" ist: Verwende ErrConnectionRefused
    • Wenn der Fehlertyp "database_not_found" ist: Verwende ErrDatabaseNotFound
    • Für jeden anderen Fehlertyp: Verwende errors.New("unknown database error")
  5. Erstelle einen umschlossenen Fehler auf Datenbankebene mit fmt.Errorf und %w: "failed to [operation] database [database_name]: %w"
  6. Erstelle einen umschlossenen Fehler auf Dienstebene: "[service_name] database operation failed after [retry_count] retries: %w"
  7. 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]"
  8. Gib die Fehlerkette aus:
    • "Error Chain:"
    • "Original: [original_error_message]"
    • "Database level: [database_level_error_message]"
    • "Service level: [service_level_error_message]"
  9. 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
	
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Logik & Ablauf

Übe selbstständig: Online-Go-Compiler