Top erreurs des développeurs Go débutants : niveau avancé

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction

Go (Golang) est réputé pour sa simplicité et sa concision. Cependant, derrière cette apparente facilité se cachent des pièges qui sont particulièrement redoutables pour les développeurs ayant déjà maîtrisé la syntaxe et les constructions de base. Passer au niveau « avancé » ne consiste pas à connaître des motifs complexes, mais à comprendre en profondeur le fonctionnement du runtime, des types et de la concurrence.

Dans cet article, nous analyserons le top des erreurs des développeurs Go débutants qui vont au-delà de « j'ai oublié de fermer un fichier » ou « j'ai confondu nil avec une erreur ». Vous apprendrez comment éviter les fuites mémoire, une mauvaise gestion des goroutines et des canaux, et vous comprendrez pourquoi nil n'est pas toujours nil.



Erreur 1 : Fuites de goroutines (Goroutine Leaks)

L'erreur la plus coûteuse en Go est de lancer une goroutine et de l'oublier. Les développeurs débutants pensent souvent que la goroutine se terminera d'elle-même une fois la fonction exécutée. Mais si la goroutine se bloque sur un canal qui ne recevra jamais de données, elle restera suspendue indéfiniment.



Problème : Canal oublié sans récepteur

func process(data []int) chan int {    out := make(chan int)    go func() {        for _, v := range data {            out <- v * 2        }        close(out)    }()    return out}

func main() { ch := process([]int{1, 2, 3}) // On lit une seule valeur, le canal ne sera pas fermé fmt.Println(<-ch) // La goroutine restera bloquée en essayant d'envoyer 4 et 6 dans le canal // time.Sleep(time.Second) — fuite mémoire}

Solution : Contrôlez toujours la durée de vie de la goroutine. Utilisez context.Context pour l'annulation ou des canaux tamponnés si vous n'êtes pas sûr du nombre de lecteurs.



func process(ctx context.Context, data []int) <-chan int {    out := make(chan int)    go func() {        defer close(out)        for _, v := range data {            select {            case out <- v * 2:            case <-ctx.Done():                return            }        }    }()    return out}


Erreur 2 : Mauvaise utilisation de select avec default

La construction select avec default est un outil puissant pour les opérations non bloquantes. Mais les débutants l'utilisent souvent comme une « béquille », ce qui conduit à une boucle active (busy-loop) avec une utilisation élevée du CPU.



Problème : Boucle infinie sans blocage

for {    select {    case msg := <-ch:        fmt.Println(msg)    default:        // On ne fait rien, mais la boucle n'est pas bloquée    }}

Un tel code va faire tourner le processeur à plein régime, consommant 100% d'un cœur. default rend le select non bloquant, et la boucle se transforme en une interrogation infinie.

Solution : Soit retirez default (alors select attendra), soit ajoutez time.Sleep ou time.Tick pour réduire la charge.



// Version correcte : sans defaultfor msg := range ch {    fmt.Println(msg)}

// Ou avec un délai d'attentefor { select { case msg := <-ch: fmt.Println(msg) case <-time.After(100 * time.Millisecond): // Vérification périodique }}


Erreur 3 : L'interface nil n'est pas nil

C'est un piège classique en Go. Une variable de type interface{} est égale à nil uniquement si son type et sa valeur sont tous deux nil. Si vous assignez à l'interface un pointeur vers nil, l'interface cesse d'être nil.



Problème : Vérification de nil via une interface

type MyError struct{}

func (e *MyError) Error() string { return "erreur"}

func getError() error { var e *MyError = nil return e // On retourne un pointeur nil, mais le type n'est pas nil}

func main() { err := getError() if err != nil { fmt.Println("Il y a une erreur !")

Blogs

Book Recommendations