Menu
Coddy logo textTech

Désenvelopper avec `errors.Is`

Fait partie de la section Logique & Flux du Journey GO de Coddy. Leçon 40 sur 68.

Lorsque vous travaillez avec des erreurs enveloppées, vous avez besoin d'un moyen de vérifier si une erreur spécifique existe n'importe où dans la chaîne d'erreurs. La fonction errors.Is offre précisément cette capacité, vous permettant d'identifier des erreurs sentinelles même lorsqu'elles ont été enveloppées plusieurs fois.

La fonction errors.Is prend deux paramètres : l'erreur que vous souhaitez examiner et l'erreur cible que vous recherchez. Elle retourne true si l'erreur cible est trouvée n'importe où dans la chaîne d'erreurs :

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

C'est la méthode moderne et recommandée pour vérifier des erreurs spécifiques en Go. Contrairement à la comparaison de chaînes ou aux vérifications d'égalité directe, errors.Is fonctionne correctement avec les erreurs enveloppées et suit la chaîne d'erreurs pour trouver des correspondances. Cela rend votre gestion des erreurs robuste et fiable, même lorsque les erreurs passent par plusieurs couches de votre application.

challenge icon

Défi

Facile

Construisez un système de surveillance des connexions à une base de données qui utilise errors.Is pour identifier des erreurs de connexion spécifiques dans des chaînes d’erreurs enveloppées. Cet exercice montre comment utiliser errors.Is pour détecter des erreurs sentinelles, même lorsqu’elles ont été enveloppées avec un contexte supplémentaire à travers plusieurs couches de l’application.

Vous recevrez deux entrées :

  • Une chaîne contenant les détails de l’opération sur la base de données au format "database_name,operation,error_type" (par exemple : "users_db,connect,connection_timeout")
  • Une chaîne contenant le contexte de l’application au format "service_name,retry_count" (par exemple : "AuthService,3")

Votre tâche consiste à :

  1. Définir trois erreurs sentinelles à l’aide de errors.New() :
    • ErrConnectionTimeout avec le message "connection timeout"
    • ErrConnectionRefused avec le message "connection refused"
    • ErrDatabaseNotFound avec le message "database not found"
  2. Analyser la première entrée en la séparant sur les virgules afin d’obtenir le nom de la base de données, l’opération et le type d’erreur
  3. Analyser la deuxième entrée en la séparant sur les virgules afin d’obtenir le nom du service et le nombre de tentatives
  4. Créer l’erreur d’origine en fonction du type d’erreur :
    • Si le type d’erreur est "connection_timeout" : utiliser ErrConnectionTimeout
    • Si le type d’erreur est "connection_refused" : utiliser ErrConnectionRefused
    • Si le type d’erreur est "database_not_found" : utiliser ErrDatabaseNotFound
    • Pour tout autre type d’erreur : utiliser errors.New("unknown database error")
  5. Créer une erreur enveloppée au niveau de la base de données à l’aide de fmt.Errorf avec %w : "failed to [operation] database [database_name]: %w"
  6. Créer une erreur enveloppée au niveau du service : "[service_name] database operation failed after [retry_count] retries: %w"
  7. Utiliser errors.Is pour vérifier si l’erreur finale enveloppée correspond à chaque erreur sentinelle et afficher les résultats :
    • "Checking for connection timeout: [true/false]"
    • "Checking for connection refused: [true/false]"
    • "Checking for database not found: [true/false]"
  8. Afficher la chaîne d’erreurs :
    • "Error Chain:"
    • "Original: [original_error_message]"
    • "Database level: [database_level_error_message]"
    • "Service level: [service_level_error_message]"
  9. Afficher l’analyse de l’erreur :
    • "Error Analysis:"
    • "Database: [database_name]"
    • "Operation: [operation]"
    • "Service: [service_name]"
    • "Retries: [retry_count]"
    • "Error type detected: [detected_error_type]", où detected_error_type est l’une des valeurs suivantes : "Connection Timeout", "Connection Refused", "Database Not Found" ou "Unknown Error"

Utilisez le package strings pour séparer les chaînes d’entrée sur les virgules, le package errors pour les erreurs sentinelles et errors.Is, ainsi que le package fmt pour envelopper les erreurs. Cet exercice montre comment errors.Is permet une identification robuste des erreurs qui fonctionne correctement avec les erreurs enveloppées, ce qui la rend essentielle pour une gestion fiable des erreurs dans les applications complexes.

Essayez vous-même

package main

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

func main() {
	// Lire l'entrée
	var dbOperation string
	var appContext string
	fmt.Scanln(&dbOperation)
	fmt.Scanln(&appContext)
	
	// Analyser les entrées
	dbParts := strings.Split(dbOperation, ",")
	databaseName := dbParts[0]
	operation := dbParts[1]
	errorType := dbParts[2]
	
	contextParts := strings.Split(appContext, ",")
	serviceName := contextParts[0]
	retryCount := contextParts[1]
	
	// TODO: Écrivez votre code ci-dessous
	// 1. Définir les trois erreurs sentinelles en utilisant errors.New()
	// 2. Créer l'erreur d'origine basée sur le type d'erreur
	// 3. Créer l'erreur enveloppée au niveau de la base de données en utilisant fmt.Errorf avec %w
	// 4. Créer l'erreur enveloppée au niveau du service
	// 5. Utiliser errors.Is pour vérifier chaque erreur sentinelle
	// 6. Afficher les résultats et la chaîne d'erreurs
	
}
quiz iconTestez-vous

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

Entraînez-vous par vous-même : Compilateur Go en ligne