0Pricing
Go Academy · Leçon

Créer des erreurs personnalisées

errors.New, fmt.Errorf et erreurs sentinelles

Créer des erreurs personnalisées est une leçon Go Academy gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Go Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Go Academy comprend 4 leçons au total.

Pourquoi créer des types d'erreur personnalisés ?

Les types d'erreur personnalisés transportent des données structurées au-delà d'un message textuel, ce qui permet aux appelants d'examiner des conditions d'erreur précises et d'y réagir :

package main
import "fmt"

// Custom error type carries extra context
type HTTPError struct {
    StatusCode int
    Message    string
}

func (e *HTTPError) Error() string {
    return fmt.Sprintf("HTTP %d: %s", e.StatusCode, e.Message)
}

func fetch(url string) error {
    return &HTTPError{404, "page not found"}
}

func main() {
    err := fetch("http://example.com")
    fmt.Println(err) // HTTP 404: page not found
}

Implémenter l'interface error

Tout type possédant une méthode Error() string satisfait l'interface error :

package main
import "fmt"

type ValidationError struct {
    Field   string
    Value   interface{}
    Message string
}

func (e *ValidationError) Error() string {
    return fmt.Sprintf("validation: field %q value %v — %s", e.Field, e.Value, e.Message)
}

func validateAge(age int) error {
    if age < 0 || age > 150 {
        return &ValidationError{"age", age, "must be between 0 and 150"}
    }
    return nil
}

func main() {
    fmt.Println(validateAge(-5))
}

Erreurs sentinelles avec errors.New

Les erreurs sentinelles sont des variables définies au niveau du paquet pour représenter des conditions d'erreur connues :

package main
import ("fmt"; "errors")

var (
    ErrNotFound      = errors.New("not found")
    ErrUnauthorized  = errors.New("unauthorized")
    ErrAlreadyExists = errors.New("already exists")
)

func getUser(id int) (string, error) {
    if id != 1 { return "", ErrNotFound }
    return "Alice", nil
}

func main() {
    _, err := getUser(99)
    if errors.Is(err, ErrNotFound) {
        fmt.Println("user does not exist")
    }
}

fmt.Errorf avec %w pour encapsuler

fmt.Errorf avec %w encapsule une erreur tout en préservant l'originale pour errors.Is et errors.As :

package main
import ("fmt"; "errors")

var ErrDatabase = errors.New("database error")

func queryDB() error {
    return fmt.Errorf("queryDB: %w", ErrDatabase)
}

func main() {
    err := queryDB()
    fmt.Println(err)                       // queryDB: database error
    fmt.Println(errors.Is(err, ErrDatabase)) // true — unwrapped
}

Erreur personnalisée avec Unwrap

Implémentez Unwrap() error sur votre type d'erreur personnalisé pour qu'il participe aux chaînes d'erreurs :

package main
import ("fmt"; "errors")

var ErrNotFound = errors.New("not found")

type QueryError struct {
    Query string
    Err   error
}

func (e *QueryError) Error() string {
    return fmt.Sprintf("query %q: %v", e.Query, e.Err)
}
func (e *QueryError) Unwrap() error { return e.Err }

func main() {
    err := &QueryError{"SELECT *", ErrNotFound}
    fmt.Println(err)
    fmt.Println(errors.Is(err, ErrNotFound)) // true
}

errors.Is — vérification de l'identité

errors.Is parcourt la chaîne d'erreurs à la recherche d'une erreur égale à la cible :

package main
import ("fmt"; "errors")

var ErrTimeout = errors.New("timeout")

func deepCall() error {
    return fmt.Errorf("layer3: %w", fmt.Errorf("layer2: %w", ErrTimeout))
}

func main() {
    err := deepCall()
    fmt.Println(errors.Is(err, ErrTimeout)) // true — found deep in chain
}

errors.As — extraction d'un type

errors.As recherche dans la chaîne la première erreur correspondant à un type cible et l'y affecte :

package main
import ("fmt"; "errors")

type PermissionError struct{ User string }
func (e *PermissionError) Error() string { return "permission denied for " + e.User }

func action(user string) error {
    return fmt.Errorf("action: %w", &PermissionError{user})
}

func main() {
    err := action("bob")
    var pe *PermissionError
    if errors.As(err, &pe) {
        fmt.Println("denied:", pe.User) // denied: bob
    }
}

Encapsulation de plusieurs erreurs (Go 1.20 et versions ultérieures)

Go 1.20 a ajouté errors.Join et fmt.Errorf avec plusieurs %w pour regrouper les erreurs :

package main
import ("fmt"; "errors")

func validate(name, email string) error {
    var errs []error
    if name == ""  { errs = append(errs, errors.New("name required")) }
    if email == "" { errs = append(errs, errors.New("email required")) }
    return errors.Join(errs...)
}

func main() {
    err := validate("", "")
    fmt.Println(err)
    // name required
    // email required
}

Conventions de nommage des types d'erreur

Conventions concernant les variables et les types d'erreur en Go :

  • Variables d'erreur sentinelle : ErrXxx (par exemple ErrNotFound)
  • Types d'erreur personnalisés : XxxError (par exemple ValidationError)
  • Variable de paquet pour une erreur sentinelle, type pointeur pour les erreurs riches
  • Exportez-les pour que les appelants puissent les utiliser avec errors.Is / errors.As

Quand utiliser chaque approche

Choisir la bonne approche pour les erreurs :

  • errors.New — simple, sans données supplémentaires, pour vérifier l'identité d'une erreur sentinelle
  • fmt.Errorf — message formaté avec encapsulation facultative
  • Type personnalisé — lorsque l'appelant a besoin de données structurées (champs, codes)
  • errors.Join — pour regrouper plusieurs erreurs de validation

Vérification rapide

Quelle fonction permet d'extraire un type d'erreur précis d'une chaîne d'erreurs ?

Récapitulatif : erreurs personnalisées

Résumé :

  • Implémentez Error() string pour créer des types d'erreur personnalisés
  • Ajoutez Unwrap() error pour participer aux chaînes d'erreurs
  • Utilisez errors.Is pour vérifier l'identité et errors.As pour extraire un type
  • Erreurs sentinelles : ErrXxx ; types personnalisés : XxxError
  • errors.Join regroupe plusieurs erreurs (Go 1.20 et versions ultérieures)

Questions Fréquemment Posées

La leçon « Créer des erreurs personnalisées » est-elle gratuite ?

Oui — le texte complet de « Créer des erreurs personnalisées » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Go Academy, passe à CoddyKit PRO. Le cours Go Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Créer des erreurs personnalisées » ?

errors.New, fmt.Errorf et erreurs sentinelles Tu pratiques Go Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Go Academy ?

Aucune expérience préalable n'est requise. Go Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.

Combien de temps prend la leçon « Créer des erreurs personnalisées » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Go Academy ?

Oui. Chaque leçon Go Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. L’interface error
  2. Créer des erreurs personnalisées
  3. Encapsuler et désencapsuler les erreurs
  4. panic, recover et defer
← Retour à Go Academy