Leçon 3/6 7 min

Fonctions et erreurs

Apprenez les fonctions Go, le retour multiple, la gestion d'erreurs explicite, defer, panic et recover.

Les fonctions

Une fonction en Go se déclare avec func. Simple, lisible, pas de surprises :

func saluer(nom string) string {
    return "Bonjour, " + nom + " !"
}

func main() {
    message := saluer("Alice")
    fmt.Println(message)
}

Remarquez que le type de retour (string) est déclaré après les paramètres, pas avant comme en C ou Java. C'est un choix de design de Go pour améliorer la lisibilité.

Sortie attendue :

Bonjour, Alice !

Retours multiples — la force de Go

En Go, une fonction peut retourner plusieurs valeurs. C'est là que Go brille par rapport aux autres langages :

func diviser(a, b float64) (float64, error) {
    if b == 0 {
        return 0, fmt.Errorf("division par zéro")
    }
    return a / b, nil
}

func main() {
    resultat, err := diviser(10, 3)
    if err != nil {
        fmt.Println("Erreur:", err)
        return
    }
    fmt.Println(resultat) // 3.3333333333333335
}

Le pattern valeur, err := fonction() est le cœur de Go. Vous le verrez partout.

Pas de try/catch — et c'est voulu

Si vous venez de JavaScript ou Python, vous connaissez try/catch. Go fait un choix radicalement différent : pas d'exceptions. Chaque erreur est une valeur retournée que vous devez gérer explicitement.

file, err := os.Open("config.json")
if err != nil {
    fmt.Println("Impossible d'ouvrir le fichier:", err)
    return
}
defer file.Close()
// Utiliser file...

Ce pattern if err != nil peut sembler répétitif au début. Mais il force le développeur à penser à chaque erreur possible. Résultat : les programmes Go plantent rarement en production.

La philosophie de Go : "Les erreurs sont des valeurs, pas des événements exceptionnels."

defer, panic, recover

defer repousse l'exécution d'une instruction à la fin de la fonction. Idéal pour le nettoyage :

func lireFichier(nom string) {
    file, err := os.Open(nom)
    if err != nil {
        fmt.Println(err)
        return
    }
    defer file.Close() // Sera exécuté à la fin, quoi qu'il arrive

    // Lire le fichier...
    fmt.Println("Fichier ouvert avec succès")
}

panic et recover existent pour les situations vraiment catastrophiques (bug dans le programme, pas une erreur utilisateur) :

func safe() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Récupéré:", r)
        }
    }()
    panic("quelque chose de terrible")
}
// Affiche: Récupéré: quelque chose de terrible

Règle d'or : utilisez error pour les erreurs normales, panic uniquement pour les bugs.

Functions

A Go function is declared with func. Simple, readable, no surprises:

func greet(name string) string {
    return "Hello, " + name + "!"
}

func main() {
    message := greet("Alice")
    fmt.Println(message)
}

Notice the return type (string) is declared after the parameters, not before like in C or Java. This is a Go design choice to improve readability.

Expected output:

Hello, Alice!

Multiple returns — Go's strength

In Go, a function can return multiple values. This is where Go shines compared to other languages:

func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, fmt.Errorf("division by zero")
    }
    return a / b, nil
}

func main() {
    result, err := divide(10, 3)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println(result) // 3.3333333333333335
}

The value, err := function() pattern is the heart of Go. You'll see it everywhere.

No try/catch — and that's on purpose

If you come from JavaScript or Python, you know try/catch. Go makes a radically different choice: no exceptions. Every error is a returned value you must handle explicitly.

file, err := os.Open("config.json")
if err != nil {
    fmt.Println("Cannot open file:", err)
    return
}
defer file.Close()
// Use file...

This if err != nil pattern may seem repetitive at first. But it forces the developer to think about every possible error. Result: Go programs rarely crash in production.

Go's philosophy: "Errors are values, not exceptional events."

defer, panic, recover

defer postpones the execution of a statement until the end of the function. Perfect for cleanup:

func readFile(name string) {
    file, err := os.Open(name)
    if err != nil {
        fmt.Println(err)
        return
    }
    defer file.Close() // Will be executed at the end, no matter what

    // Read the file...
    fmt.Println("File opened successfully")
}

panic and recover exist for truly catastrophic situations (bug in the program, not a user error):

func safe() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered:", r)
        }
    }()
    panic("something terrible")
}
// Prints: Recovered: something terrible

Golden rule: use error for normal errors, panic only for bugs.

Testez dans le Go Playground

Testez la fonction diviser et essayez de diviser par zéro :

Avec l'IA

Copiez ce prompt dans Claude ou ChatGPT :

Écris une fonction Go qui lit un fichier JSON et retourne son contenu dans un struct. Gère toutes les erreurs possibles (fichier introuvable, JSON invalide). Explique chaque if err != nil.
Combien de valeurs une fonction Go peut-elle retourner ?
Comment Go gère-t-il les erreurs ?
Que fait le mot-clé defer ?
Quand utiliser panic en Go ?
Besoin d'un développeur pour votre projet ?

Réponse sous 24h — Sans engagement