Menu
Coddy logo textTech

Unwrapping mit `errors.As`

Teil des Abschnitts Logik & Ablauf der GO-Journey von Coddy — Lektion 41 von 68.

Während errors.Is Ihnen hilft, spezifische Fehlerwerte in einer Kette zu identifizieren, müssen Sie manchmal auf die tatsächlichen Felder und Daten eines benutzerdefinierten Fehlertyps zugreifen. Die Funktion errors.As bietet diese Möglichkeit, indem sie den ersten Fehler in einer Kette findet, der einem bestimmten Typ entspricht, und ihn zur Untersuchung extrahiert.

Die Funktion errors.As nimmt zwei Parameter entgegen: den zu untersuchenden Fehler und einen Pointer auf eine Variable des Ziel-Fehlertyps. Wenn sie einen passenden Fehlertyp in der Kette findet, setzt sie Ihre Variable auf diesen Fehler und gibt true zurück:

var validationErr ValidationError
if errors.As(wrappedErr, &validationErr) {
    fmt.Printf("Field: %s, Message: %s\n", validationErr.Field, validationErr.Message)
}

Dies ist besonders leistungsfähig bei der Arbeit mit benutzerdefinierten Fehlertypen, die zusätzlichen Kontext enthalten. Im Gegensatz zu errors.Is, das nur auf Gleichheit prüft, extrahiert errors.As die tatsächliche Fehlerinstanz, was es Ihnen ermöglicht, auf deren Felder und Methoden zuzugreifen. Dies macht die Fehlerbehandlung in komplexen Anwendungen anspruchsvoller und informativer.

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 API-Fehlerbehandlungssystem, das errors.As verwendet, um benutzerdefinierte Fehlertypen aus verschachtelten Fehlerketten zu extrahieren und zu untersuchen. Diese Herausforderung zeigt, wie man errors.As einsetzt, um auf die Felder und Daten spezifischer benutzerdefinierter Fehlertypen zuzugreifen, selbst wenn diese mit zusätzlichem Kontext umschlossen (wrapped) wurden.

Sie erhalten zwei Eingaben:

  • Einen String mit API-Anforderungsdetails im Format "endpoint,method,error_code,error_field" (z. B. "/users,POST,400,email")
  • Einen String mit Systemkontext im Format "service_name,request_id" (z. B. "UserAPI,req_12345")

Ihre Aufgabe ist es:

  1. Erstellen Sie einen benutzerdefinierten Fehlertyp namens APIError als Struct mit drei Feldern:
    • Code (int) - der HTTP-Statuscode
    • Field (string) - das Feld, das den Fehler verursacht hat
    • Message (string) - eine Beschreibung des Fehlers
  2. Implementieren Sie die Methode Error() string für APIError, die Folgendes zurückgibt: "API error [code]: [message] (field: [field])"
  3. Parsen Sie die erste Eingabe, indem Sie sie an Kommas trennen, um Endpoint, Method, Error Code und Error Field zu erhalten
  4. Parsen Sie die zweite Eingabe, indem Sie sie an Kommas trennen, um Service Name und Request ID zu erhalten
  5. Konvertieren Sie den Fehlercode-String in eine Ganzzahl (Integer)
  6. Erstellen Sie eine APIError-Instanz basierend auf dem Fehlercode:
    • Wenn der Code 400 ist: Nachricht "invalid request data"
    • Wenn der Code 401 ist: Nachricht "authentication required"
    • Wenn der Code 404 ist: Nachricht "resource not found"
    • Wenn der Code 500 ist: Nachricht "internal server error"
    • Für jeden anderen Code: Nachricht "unknown error"
  7. Erstellen Sie einen Fehler auf Endpoint-Ebene mit fmt.Errorf und %w: "[method] [endpoint] failed: %w"
  8. Erstellen Sie einen Fehler auf Service-Ebene: "[service_name] request [request_id] failed: %w"
  9. Verwenden Sie errors.As, um den APIError aus der verschachtelten Fehlerkette zu extrahieren und das Ergebnis der Extraktion anzuzeigen:
    • Wenn die Extraktion erfolgreich ist: "API error extracted successfully"
    • Wenn die Extraktion fehlschlägt: "Failed to extract API error"
  10. Wenn die Extraktion erfolgreich war, zeigen Sie die Details des extrahierten Fehlers an:
    • "Extracted Error Details:"
    • "Code: [code]"
    • "Field: [field]"
    • "Message: [message]"
    • "Full error: [full_error_message_from_Error_method]"
  11. Zeigen Sie die vollständige Fehlerkette an:
    • "Error Chain:"
    • "Original: [original_api_error_message]"
    • "Endpoint level: [endpoint_level_error_message]"
    • "Service level: [service_level_error_message]"
  12. Zeigen Sie eine abschließende Analyse an:
    • "Error Analysis:"
    • "Service: [service_name]"
    • "Request ID: [request_id]"
    • "Endpoint: [method] [endpoint]"
    • "HTTP Status: [code]"
    • "Problem Field: [field]"
    • "Error Category: [error_category]" wobei error_category "Client Error" für Codes 400-499, "Server Error" für Codes 500-599 oder "Unknown" für andere Codes ist

Verwenden Sie das Paket strings, um die Eingabestrings an Kommas zu trennen, das Paket strconv, um den Fehlercode-String in einen Integer umzuwandeln, das Paket errors für errors.As und das Paket fmt für das Error-Wrapping. Diese Herausforderung zeigt, wie errors.As es Ihnen ermöglicht, auf die spezifischen Felder und Methoden benutzerdefinierter Fehlertypen innerhalb verschachtelter Fehlerketten zuzugreifen, was eine anspruchsvolle Fehlerbehandlung und -analyse ermöglicht.

Spickzettel

Die Funktion errors.As extrahiert spezifische Fehlertypen aus Fehlerketten und ermöglicht so den Zugriff auf benutzerdefinierte Fehlerfelder und -methoden.

errors.As nimmt zwei Parameter entgegen: den zu untersuchenden Fehler und einen Zeiger auf eine Variable des Ziel-Fehlertyps:

var validationErr ValidationError
if errors.As(wrappedErr, &validationErr) {
    fmt.Printf("Field: %s, Message: %s\n", validationErr.Field, validationErr.Message)
}

Im Gegensatz zu errors.Is, das nur auf Gleichheit prüft, extrahiert errors.As die tatsächliche Fehlerinstanz und ermöglicht so den Zugriff auf deren Felder und Methoden für eine anspruchsvollere Fehlerbehandlung.

Probier es selbst

package main

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
)

func main() {
	// Eingabe lesen
	var apiDetails string
	var systemContext string
	fmt.Scanln(&apiDetails)
	fmt.Scanln(&systemContext)
	
	// Eingaben parsen
	apiParts := strings.Split(apiDetails, ",")
	endpoint := apiParts[0]
	method := apiParts[1]
	errorCodeStr := apiParts[2]
	errorField := apiParts[3]
	
	contextParts := strings.Split(systemContext, ",")
	serviceName := contextParts[0]
	requestID := contextParts[1]
	
	// Fehlercode in Ganzzahl umwandeln
	errorCode, _ := strconv.Atoi(errorCodeStr)
	
	// TODO: Schreiben Sie Ihren Code unten
	// 1. APIError-Struktur mit den Feldern Code, Field, Message erstellen
	// 2. Error()-Methode für APIError implementieren
	// 3. APIError-Instanz basierend auf dem Fehlercode erstellen
	// 4. Eingepackte Fehler erstellen (Endpunkt-Ebene und Service-Ebene)
	// 5. errors.As verwenden, um APIError aus der Kette der eingepackten Fehler zu extrahieren
	// 6. Extraktionsergebnis und Fehlerdetails anzeigen
	// 7. Fehlerkette und abschließende Analyse anzeigen
	
}
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