Laisser un canal ouvert en Go : possible ou pas ? Analyse pour débutants

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 : la question qui tourmente un débutant sur deux en Go



Imaginez : vous écrivez votre premier programme sérieux en Go. Vous avez compris les goroutines, maîtrisé les canaux et même écrit quelques exemples fonctionnels. Mais soudain, vous tombez sur Stack Overflow sur une question qui a rassemblé des milliers de vues : "Is it OK to leave a channel open?" (Peut-on laisser un canal ouvert ?).



Spoiler : la réponse n'est pas aussi tranchée qu'on le souhaiterait. Certains crient qu'un canal non fermé est un péché mortel et une fuite de ressources. D'autres disent que le garbage collector en Go nettoie tout. Où est la vérité ? Analysons cela avec des exemples concrets, sans blabla ni cours académiques.



Pour ceux qui découvrent le langage — Go (ou Golang) propose un mécanisme élégant de synchronisation via les canaux. Mais comme tout outil puissant, les canaux nécessitent une manipulation soigneuse. Surtout lorsqu'il s'agit de leur fermeture.



Pourquoi cette question s'est-elle posée ? La racine du problème



En Go, il y a un dicton : « Ne fermez pas le canal du côté du récepteur — fermez-le du côté de l'émetteur ». Mais que faire si le programme se termine et que le canal reste ouvert ? La fuite de goroutines — voilà la principale peur. Lorsqu'une goroutine « reste en attente » de données provenant d'un canal que personne ne fermera jamais, elle ne se termine pas. Et des goroutines non terminées, c'est une fuite mémoire et un production tué.



Mais soyons honnêtes : dans les petits scripts ou les utilitaires de test, ce n'est pas grave. Le garbage collector en Go est intelligent, mais il ne nettoie pas les goroutines — seulement la mémoire qu'elles occupent. Donc la question « fermer ou non » dépend de l'architecture de votre application.



Exemple 1 : quand NE PAS fermer un canal est normal



Considérons un scénario simple : un programme lit des données, les traite et se termine. Si le canal est utilisé uniquement dans main, et que vous savez précisément que toutes les goroutines se termineront — vous pouvez ne pas le fermer.



package main

import "fmt"

func main() { ch := make(chan int)

// Goroutine émettrice go func() { for i := 0; i < 5; i++ { ch <- i } // Canal NON fermé }()

// Récepteur for i := 0; i < 5; i++ { fmt.Println(<-ch) } // Le programme se termine sans erreur fmt.Println("Terminé, le canal est resté ouvert, mais tout va bien")}


Pourquoi cela fonctionne-t-il ? Parce que main se termine, et toutes les goroutines sont détruites avec le processus. Le garbage collector Go nettoiera la mémoire. Il n'y a aucune fuite de goroutines — le programme s'est simplement terminé.



Conclusion : si votre programme est un script qui se lance et s'arrête, laisser un canal ouvert est tout à fait normal. Cela n'entraînera pas de fuite si vous contrôlez le cycle de vie.



Exemple 2 : quand un canal non fermé est une catastrophe



Imaginez maintenant un serveur qui fonctionne 24h/24. Vous avez une goroutine qui écoute le canal en continu :



package main

import ( "fmt" "time")

func worker(ch chan int) { // Lecture infinie for val := range ch { fmt.Println("Traité :", val) } // Nous n'arriverons jamais ici si le canal n'est pas fermé fmt.Println("Goroutine terminée")}

func main() { ch := make(chan int) go worker(ch)

// Envoi de données ch <- 1 ch <- 2 ch <- 3

// On oublie de fermer le canal // close(ch)

time.Sleep(2 * time.Second) fmt.Println("Le programme se termine, mais le worker est toujours en attente !")}


Que va-t-il se passer ? La goroutine worker restera bloquée dans une boucle infinie, attendant de nouvelles données. Elle ne se terminera jamais. La fuite de goroutines est évidente. Avec le temps, des dizaines de milliers de ces goroutines s'accumuleront, et le serveur plantera avec une erreur mémoire.



Dans ce cas, la fermeture du canal est obligatoire. C'est précisément close(ch) qui donne le signal à la go

Blogs

Book Recommendations