Rimuovere il wrapping con `errors.As`
Fa parte della sezione Logica e flusso del percorso GO di Coddy. Lezione 41 di 68.
Mentre errors.Is ti aiuta a identificare specifici valori di errore in una catena, a volte devi accedere ai campi e ai dati effettivi di un tipo di errore personalizzato. La funzione errors.As offre questa possibilità, trovando il primo errore in una catena che corrisponde a un tipo specifico ed estraendolo per esaminarlo.
La funzione errors.As accetta due parametri: l'errore da esaminare e un puntatore a una variabile del tipo di errore target. Se trova un tipo di errore corrispondente nella catena, assegna quell'errore alla tua variabile e restituisce true:
var validationErr ValidationError
if errors.As(wrappedErr, &validationErr) {
fmt.Printf("Field: %s, Message: %s\n", validationErr.Field, validationErr.Message)
}Questo è particolarmente efficace quando si lavora con tipi di errore personalizzati che contengono un contesto aggiuntivo. A differenza di errors.Is, che controlla solo l'uguaglianza, errors.As estrae l'istanza effettiva dell'errore, consentendoti di accedere ai suoi campi e metodi. Questo rende la gestione degli errori più sofisticata e informativa nelle applicazioni complesse.
Sfida
FacileCrea un sistema di gestione degli errori API che utilizzi errors.As per estrarre ed esaminare tipi di errore personalizzati da catene di errori avvolti. Questa sfida mostra come usare errors.As per accedere ai campi e ai dati di specifici tipi di errore personalizzati, anche quando sono stati avvolti con ulteriore contesto.
Riceverai due input:
- Una stringa contenente i dettagli della richiesta API nel formato
"endpoint,method,error_code,error_field"(ad esempio,"/users,POST,400,email") - Una stringa contenente il contesto di sistema nel formato
"service_name,request_id"(ad esempio,"UserAPI,req_12345")
Il tuo compito è:
- Creare un tipo di errore personalizzato chiamato struct
APIErrorcon tre campi:Code(int) - il codice di stato HTTPField(string) - il campo che ha causato l'erroreMessage(string) - una descrizione dell'errore
- Implementare il metodo
Error() stringperAPIError, che restituisca:"API error [code]: [message] (field: [field])" - Analizzare il primo input suddividendolo in corrispondenza delle virgole per ottenere endpoint, method, error code ed error field
- Analizzare il secondo input suddividendolo in corrispondenza delle virgole per ottenere il nome del servizio e l'ID della richiesta
- Convertire la stringa del codice di errore in un intero
- Creare un'istanza di
APIErrorin base al codice di errore:- Se il codice è 400: messaggio
"invalid request data" - Se il codice è 401: messaggio
"authentication required" - Se il codice è 404: messaggio
"resource not found" - Se il codice è 500: messaggio
"internal server error" - Per qualsiasi altro codice: messaggio
"unknown error"
- Se il codice è 400: messaggio
- Creare un errore avvolto a livello di endpoint usando
fmt.Errorfcon%w:"[method] [endpoint] failed: %w" - Creare un errore avvolto a livello di servizio:
"[service_name] request [request_id] failed: %w" - Usare
errors.Asper estrarreAPIErrordalla catena di errori avvolti e mostrare il risultato dell'estrazione:- Se l'estrazione riesce:
"API error extracted successfully" - Se l'estrazione non riesce:
"Failed to extract API error"
- Se l'estrazione riesce:
- Se l'estrazione è riuscita, mostrare i dettagli dell'errore estratto:
"Extracted Error Details:""Code: [code]""Field: [field]""Message: [message]""Full error: [full_error_message_from_Error_method]"
- Mostrare la catena di errori completa:
"Error Chain:""Original: [original_api_error_message]""Endpoint level: [endpoint_level_error_message]""Service level: [service_level_error_message]"
- Mostrare un'analisi finale:
"Error Analysis:""Service: [service_name]""Request ID: [request_id]""Endpoint: [method] [endpoint]""HTTP Status: [code]""Problem Field: [field]""Error Category: [error_category]", dove error_category è "Client Error" per i codici 400-499, "Server Error" per i codici 500-599 oppure "Unknown" per gli altri codici
Usa il pacchetto strings per suddividere le stringhe di input in corrispondenza delle virgole, il pacchetto strconv per convertire la stringa del codice di errore in un intero, il pacchetto errors per errors.As e il pacchetto fmt per avvolgere gli errori. Questa sfida mostra come errors.As consenta di accedere ai campi e ai metodi specifici dei tipi di errore personalizzati all'interno di catene di errori avvolti, permettendo una gestione e un'analisi sofisticate degli errori.
Provalo tu
package main
import (
"errors"
"fmt"
"strconv"
"strings"
)
func main() {
// Leggi l'input
var apiDetails string
var systemContext string
fmt.Scanln(&apiDetails)
fmt.Scanln(&systemContext)
// Analizza gli input
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]
// Converti il codice di errore in un numero intero
errorCode, _ := strconv.Atoi(errorCodeStr)
// TODO: Scrivi il tuo codice qui sotto
// 1. Crea la struct APIError con i campi Code, Field e Message
// 2. Implementa il metodo Error() per APIError
// 3. Crea un'istanza di APIError in base al codice di errore
// 4. Crea errori incapsulati (a livello di endpoint e di servizio)
// 5. Usa errors.As per estrarre APIError dalla catena di errori incapsulati
// 6. Mostra il risultato dell'estrazione e i dettagli dell'errore
// 7. Mostra la catena degli errori e l'analisi finale
}Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Logica e flusso
1Flusso di controllo avanzato
Switch con `fallthrough`Uscire dai cicli annidatiContinuare un ciclo specificoL'istruzione `goto`Riepilogo - Controllo avanzato dei cicli4Progetto: semplice lista di attività
Configurazione del progettoAggiungere un’attività7Gestione degli errori in dettaglio
Tipi di errore personalizzatiAvvolgere gli errori con `%w`Rimuovere il wrapping con `errors.Is`Rimuovere il wrapping con `errors.As`Capire `panic`Usare `recover`Riepilogo - Divisione sicura2Struct e metodi
Definire metodi sugli structReceiver per valoreReceiver con puntatoreScegliere i receiverMetodi vs funzioniRiepilogo - comportamento degli struct5Mappe in dettaglio
Mappe di structPuntatori come valori delle mappeVerificare le mappe nilConfrontare le mappeRiepilogo - Contatore della frequenza delle parole3Interfacce (le basi)
Che cos’è un’interfaccia?Definire un’interfacciaImplementare un’interfacciaUsare i tipi interfacciaInterfaccia vuotaAsserzioni di tipoSwitch di tipoRiepilogo: forme e comportamentiEsercitati da solo: Compilatore Go online