Désenvelopper avec `errors.As`
Fait partie de la section Logique & Flux du Journey GO de Coddy — leçon 41 sur 68.
Alors que errors.Is vous aide à identifier des valeurs d'erreur spécifiques dans une chaîne, vous avez parfois besoin d'accéder aux champs et aux données réels d'un type d'erreur personnalisé. La fonction errors.As offre cette possibilité en trouvant la première erreur dans une chaîne qui correspond à un type spécifique et en l'extrayant pour inspection.
La fonction errors.As prend deux paramètres : l'erreur à examiner et un pointeur vers une variable du type d'erreur cible. Si elle trouve un type d'erreur correspondant dans la chaîne, elle affecte cette erreur à votre variable et renvoie true :
var validationErr ValidationError
if errors.As(wrappedErr, &validationErr) {
fmt.Printf("Field: %s, Message: %s\n", validationErr.Field, validationErr.Message)
}Ceci est particulièrement puissant lors de l'utilisation de types d'erreurs personnalisés qui contiennent un contexte supplémentaire. Contrairement à errors.Is qui vérifie uniquement l'égalité, errors.As extrait l'instance d'erreur réelle, vous permettant d'accéder à ses champs et méthodes. Cela rend la gestion des erreurs plus sophistiquée et informative dans les applications complexes.
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Défi
FacileConstruisez un système de gestion des erreurs d'API qui utilise errors.As pour extraire et examiner des types d'erreurs personnalisés à partir de chaînes d'erreurs enveloppées (wrapped). Ce défi démontre comment utiliser errors.As pour accéder aux champs et aux données de types d'erreurs personnalisés spécifiques, même lorsqu'ils ont été enveloppés avec un contexte supplémentaire.
Vous recevrez deux entrées :
- Une chaîne contenant les détails de la requête API au format
"endpoint,method,error_code,error_field"(par exemple,"/users,POST,400,email") - Une chaîne contenant le contexte du système au format
"service_name,request_id"(par exemple,"UserAPI,req_12345")
Votre tâche consiste à :
- Créer un type d'erreur personnalisé appelé struct
APIErroravec trois champs :Code(int) - le code d'état HTTPField(string) - le champ qui a causé l'erreurMessage(string) - une description de l'erreur
- Implémenter la méthode
Error() stringpourAPIErrorqui retourne :"API error [code]: [message] (field: [field])" - Analyser la première entrée en la divisant par les virgules pour obtenir l'endpoint, la méthode, le code d'erreur et le champ d'erreur
- Analyser la seconde entrée en la divisant par les virgules pour obtenir le nom du service et l'ID de la requête
- Convertir la chaîne du code d'erreur en un entier
- Créer une instance de
APIErrorbasée sur le code d'erreur :- Si le code est 400 : message
"invalid request data" - Si le code est 401 : message
"authentication required" - Si le code est 404 : message
"resource not found" - Si le code est 500 : message
"internal server error" - Pour tout autre code : message
"unknown error"
- Si le code est 400 : message
- Créer une erreur enveloppée au niveau de l'endpoint en utilisant
fmt.Errorfavec%w:"[method] [endpoint] failed: %w" - Créer une erreur enveloppée au niveau du service :
"[service_name] request [request_id] failed: %w" - Utiliser
errors.Aspour extraire l'APIErrorde la chaîne d'erreurs enveloppées et afficher le résultat de l'extraction :- Si l'extraction réussit :
"API error extracted successfully" - Si l'extraction échoue :
"Failed to extract API error"
- Si l'extraction réussit :
- Si l'extraction a réussi, afficher les détails de l'erreur extraite :
"Extracted Error Details:""Code: [code]""Field: [field]""Message: [message]""Full error: [full_error_message_from_Error_method]"
- Afficher la chaîne d'erreurs complète :
"Error Chain:""Original: [original_api_error_message]""Endpoint level: [endpoint_level_error_message]""Service level: [service_level_error_message]"
- Afficher une analyse finale :
"Error Analysis:""Service: [service_name]""Request ID: [request_id]""Endpoint: [method] [endpoint]""HTTP Status: [code]""Problem Field: [field]""Error Category: [error_category]"où error_category est "Client Error" pour les codes 400-499, "Server Error" pour les codes 500-599, ou "Unknown" pour les autres codes
Utilisez le package strings pour diviser les chaînes d'entrée sur les virgules, le package strconv pour convertir la chaîne du code d'erreur en entier, le package errors pour errors.As, et le package fmt pour l'enveloppement d'erreurs. Ce défi démontre comment errors.As vous permet d'accéder aux champs et méthodes spécifiques des types d'erreurs personnalisés au sein des chaînes d'erreurs enveloppées, permettant ainsi une gestion et une analyse sophistiquées des erreurs.
Aide-mémoire
La fonction errors.As extrait des types d'erreurs spécifiques à partir de chaînes d'erreurs, permettant l'accès aux champs et méthodes d'erreurs personnalisés.
errors.As prend deux paramètres : l'erreur à examiner et un pointeur vers une variable du type d'erreur cible :
var validationErr ValidationError
if errors.As(wrappedErr, &validationErr) {
fmt.Printf("Field: %s, Message: %s\n", validationErr.Field, validationErr.Message)
}Contrairement à errors.Is qui vérifie uniquement l'égalité, errors.As extrait l'instance d'erreur réelle, permettant l'accès à ses champs et méthodes pour une gestion d'erreurs plus sophistiquée.
Essayez vous-même
package main
import (
"errors"
"fmt"
"strconv"
"strings"
)
func main() {
// Lire l'entrée
var apiDetails string
var systemContext string
fmt.Scanln(&apiDetails)
fmt.Scanln(&systemContext)
// Analyser les entrées
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]
// Convertir le code d'erreur en entier
errorCode, _ := strconv.Atoi(errorCodeStr)
// TODO: Écrivez votre code ci-dessous
// 1. Créer la structure APIError avec les champs Code, Field, Message
// 2. Implémenter la méthode Error() pour APIError
// 3. Créer une instance d'APIError basée sur le code d'erreur
// 4. Créer des erreurs enveloppées (au niveau de l'endpoint et du service)
// 5. Utiliser errors.As pour extraire APIError de la chaîne d'erreurs enveloppées
// 6. Afficher le résultat de l'extraction et les détails de l'erreur
// 7. Afficher la chaîne d'erreurs et l'analyse finale
}Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Logique & Flux
1Structures de contrôle avancées
Switch avec `fallthrough`Sortir de boucles imbriquéesContinuer une boucle spécifiqueL'instruction `goto`Récapitulatif - Contrôle de boucle avancé4Projet : Liste de tâches simple
Configuration du projetAjouter une tâche7Gestion des erreurs en profondeur
Types d'erreurs personnalisésEnvelopper des erreurs avec `%w`Désenvelopper avec `errors.Is`Désenvelopper avec `errors.As`Comprendre `panic`Utiliser `recover`Récapitulatif - Division sécurisée2Structures et Méthodes
Définir des méthodes sur des structuresReceveurs par valeurReceveurs par pointeurChoisir les receveursMéthodes vs FonctionsRécapitulatif - Comportement des structures5Les Maps en profondeur
Maps de StructsPointeurs comme valeurs de MapTester les Maps NilComparer des MapsRécapitulatif - Compteur de fréquence de mots3Interfaces (Les bases)
Qu'est-ce qu'une Interface ?Définir une InterfaceImplémenter une InterfaceUtiliser les types d'InterfaceInterface videAssertions de typeType SwitchRécapitulatif - Formes et comportements