Maison  >  Article  >  développement back-end  >  Comment terminer gracieusement les Goroutines et gérer les erreurs dans Go ?

Comment terminer gracieusement les Goroutines et gérer les erreurs dans Go ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-11-12 07:21:02924parcourir

How to Gracefully Terminate Goroutines and Handle Errors in Go?

Terminaison idiomatique de Goroutine et gestion des erreurs : une étude de cas

Dans Go, la gestion de la terminaison de Goroutine est souvent un défi pour les développeurs. Un problème courant consiste à assurer un nettoyage approprié des goroutines lorsqu'une erreur se produit. Cet article présente une solution élégante et idiomatique à ce problème en utilisant le regroupement d'erreurs.

Considérez l'exemple suivant :

package main

import (
        "sync"
        "time"
)

func fetchAll() error {
        wg := sync.WaitGroup{}
        errs := make(chan error)

        // run all the http requests in parallel
        for i := 0; i < 4; i++ {
                wg.Add(1)
                go func(i int) {
                        defer wg.Done()

                        // pretend this does an http request and returns an error
                        time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
                        errs <- fmt.Errorf("goroutine %d's error returned", i)
                }(i)
        }

        // wait until all the fetches are done and close the error
        // channel so the loop below terminates
        go func() {
                wg.Wait()
                close(errs)
        }()

        // return the first error
        for err := range errs {
                if err != nil {
                        return err
                }
        }

        return nil
}

Cette implémentation présente un défaut critique : elle laisse fuir les goroutines. Le correctif consiste à utiliser un groupe d'erreurs :

package main

import (
        "context"
        "fmt"
        "math/rand"
        "time"

        "golang.org/x/sync/errgroup"
)

func fetchAll(ctx context.Context) error {
        errs, ctx := errgroup.WithContext(ctx)

        // run all the http requests in parallel
        for i := 0; i < 4; i++ {
                errs.Go(func() error {
                        // pretend this does an http request and returns an error                                                  
                        time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)                                               
                        return fmt.Errorf("error in go routine, bailing")                                                      
                })
        }

        // Wait for completion and return the first error (if any)                                                                 
        return errs.Wait()
}

Un groupe d'erreurs attend automatiquement que toutes les goroutines se terminent avec succès ou annule celles restantes en cas d'erreur. Dans le cas ci-dessus, la première goroutine qui rencontre une erreur déclenche l'annulation de toutes les autres et l'erreur est propagée à l'appelant. L'utilisation du contexte garantit une terminaison gracieuse lorsque le contexte environnant est annulé.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn