ProgrammationDéveloppeur Backend

Qu'est-ce qu'une fuite de goroutine en Go et comment les éviter ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Historique de la question :

Une fuite de goroutine est une situation où une goroutine continue d'exister et reste en mémoire, bien qu'elle soit en fait "devenue inutile" (les calculs sont terminés, les données ne sont plus nécessaires, mais il n'y a pas de condition de sortie). Cela ressemble aux fuites de mémoire, mais pour les fils d'exécution. C'est critique pour Go : une charge importante peut entraîner l'épuisement des ressources.

Problème :

Contrairement à d'autres langages, où la gestion directe des threads conduit souvent à leur fermeture manuelle, en Go, les goroutines sont lancées facilement, mais se terminent pas toujours correctement. Une erreur fréquente : la logique principale est terminée, mais la goroutine est "gelée" - elle attend des données sur un canal fermé ou ne recevra jamais le signal.

Solution :

Pour éviter les fuites, on utilise des constructions de contrôle : context, fermeture de canaux, variables de signalisation. Il est important de concevoir à l'avance les chemins de sortie de chaque goroutine, d'utiliser defer pour le nettoyage. Exemple :

func worker(ctx context.Context, jobs <-chan int, results chan<- int) { for { select { case <-ctx.Done(): return case job, ok := <-jobs: if !ok { return } results <- job * 2 } } }

Caractéristiques clés :

  • Contrôlez tout le cycle de vie de la goroutine
  • Utilisez le contexte pour une fermeture contrôlée
  • Fermez les canaux après utilisation

Questions pièges.

Peut-on simplement fermer le canal pour arrêter la Goroutine ?

Pas toujours. Si le select a d'autres cas ou s'il n'y a pas de vérification de fermeture via ok, la goroutine peut rester "suspendue".

val, ok := <-ch if !ok { return } // C'est plus correct

Que se passera-t-il si vous oubliez de gérer context.Done dans le select ?

La goroutine ne saura jamais que l'annulation a eu lieu - elle restera "éternelle". C'est un chemin direct vers une fuite.

Peut-on détecter une fuite avec go runtime ?

Il n'existe pas d'outil standard pour suivre les fuites. Il est nécessaire de surveiller le nombre de goroutines actives via runtime.NumGoroutine ou d'utiliser un détecteur de fuites d'une bibliothèque tierce.

Erreurs typiques et anti-patterns

  • Attendre sur un canal inexistant ou bloqué
  • Lancer des goroutines infinies sans voies de sortie
  • Incohérence dans la fermeture des canaux

Exemple de la vie réelle

Cas négatif

Dans le système d'envoi de notifications push, une goroutine est lancée pour chaque message entrant, mais on oublie de les arrêter lors de l'annulation du contexte ou de la fermeture du canal - des centaines de goroutines "mortes" restent en mémoire.

Avantages :

  • Simple à lancer, prototypage rapide

Inconvénients :

  • Augmentation de la mémoire
  • Ralentissement de l'ordonnanceur

Cas positif

Le travail de la goroutine est contrôlé par le contexte, au niveau de la logique métier, on vérifie la sortie du select, après un envoi/traitement réussi, le canal est fermé.

Avantages :

  • Pas de fuites
  • Facile à suivre et à profiler

Inconvénients :

  • Nécessite une conception soignée des canaux et des threads