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 verschachtelten Fehlern benötigen Sie eine Möglichkeit zu prüfen, ob ein bestimmter Fehler irgendwo in der Fehlerkette existiert. Die Funktion errors.Is bietet genau diese Funktionalität und ermöglicht es Ihnen, Sentinel-Fehler zu identifizieren, selbst wenn diese mehrfach verschachtelt 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.

quiz iconTeste dich selbst

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

quiz iconTeste dich selbst

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

quiz iconTeste dich selbst

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

challenge icon

Aufgabe

Einfach

Erstellen Sie ein Datenbankverbindungs-Überwachungssystem, das errors.Is verwendet, um spezifische Verbindungsfehler in verschachtelten Fehlerketten (wrapped error chains) zu identifizieren. Diese Herausforderung zeigt, wie man errors.Is einsetzt, um Sentinel-Fehler zu erkennen, selbst wenn diese durch mehrere Anwendungsschichten mit zusätzlichem Kontext umschlossen wurden.

Sie erhalten zwei Eingaben:

  • Einen String mit Details zur Datenbankoperation im Format "database_name,operation,error_type" (z. B. "users_db,connect,connection_timeout")
  • Einen String mit dem Anwendungskontext im Format "service_name,retry_count" (z. B. "AuthService,3")

Ihre Aufgabe ist es:

  1. Definieren Sie 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. Parsen Sie die erste Eingabe, indem Sie sie an den Kommas trennen, um Datenbankname, Operation und Fehlertyp zu erhalten
  3. Parsen Sie die zweite Eingabe, indem Sie sie an den Kommas trennen, um Servicename und Anzahl der Versuche (retry count) zu erhalten
  4. Erstellen Sie den ursprünglichen Fehler basierend auf dem Fehlertyp:
    • Wenn der Fehlertyp "connection_timeout" ist: verwenden Sie ErrConnectionTimeout
    • Wenn der Fehlertyp "connection_refused" ist: verwenden Sie ErrConnectionRefused
    • Wenn der Fehlertyp "database_not_found" ist: verwenden Sie ErrDatabaseNotFound
    • Für jeden anderen Fehlertyp: verwenden Sie errors.New("unknown database error")
  5. Erstellen Sie einen verschachtelten Fehler auf Datenbankebene mit fmt.Errorf und %w: "failed to [operation] database [database_name]: %w"
  6. Erstellen Sie einen verschachtelten Fehler auf Serviceebene: "[service_name] database operation failed after [retry_count] retries: %w"
  7. Verwenden Sie errors.Is, um zu prüfen, ob der finale verschachtelte Fehler mit jedem Sentinel-Fehler übereinstimmt, und geben Sie die Ergebnisse aus:
    • "Checking for connection timeout: [true/false]"
    • "Checking for connection refused: [true/false]"
    • "Checking for database not found: [true/false]"
  8. Geben Sie die Fehlerkette aus:
    • "Error Chain:"
    • "Original: [original_error_message]"
    • "Database level: [database_level_error_message]"
    • "Service level: [service_level_error_message]"
  9. Geben Sie 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 einer der Werte "Connection Timeout", "Connection Refused", "Database Not Found" oder "Unknown Error" ist

Verwenden Sie das strings-Paket, um die Eingabestrings an den Kommas zu trennen, das errors-Paket für Sentinel-Fehler und errors.Is, sowie das fmt-Paket für das Error-Wrapping. Diese Herausforderung zeigt, wie errors.Is eine robuste Fehleridentifizierung ermöglicht, die korrekt mit verschachtelten Fehlern funktioniert, was für eine zuverlässige Fehlerbehandlung in komplexen Anwendungen unerlässlich ist.

Spickzettel

Die Funktion errors.Is prüft, ob ein bestimmter Fehler irgendwo in einer Fehlerkette existiert, selbst wenn er mehrfach verschachtelt (wrapped) ist:

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")
}

errors.Is nimmt zwei Parameter entgegen: den zu untersuchenden Fehler und den zu suchenden Zielfehler. Sie gibt true zurück, wenn der Zielfehler irgendwo in der Fehlerkette gefunden wird.

Dies ist die moderne, empfohlene Methode, um in Go auf spezifische Fehler zu prüfen, da sie im Gegensatz zu String-Vergleichen oder direkten Gleichheitsprüfungen korrekt mit verschachtelten Fehlern funktioniert.

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