Maison  >  Article  >  développement back-end  >  Comment implémenter un délai d'attente pour WaitGroup.Wait() dans Go ?

Comment implémenter un délai d'attente pour WaitGroup.Wait() dans Go ?

Susan Sarandon
Susan Sarandonoriginal
2024-11-12 17:17:01877parcourir

How to Implement a Timeout for WaitGroup.Wait() in Go?

Délai d'expiration pour WaitGroup.Wait() : approches idiomatiques

Dans Go, une limite de temps peut être définie pour WaitGroup.Wait() pour éviter une attente infinie pour les travailleurs errants . Voici une exploration détaillée des façons idiomatiques de la mettre en œuvre et des approches alternatives.

Solution recommandée : utiliser une minuterie et un canal

L'approche suivante est largement considérée comme la solution la plus idiomatique :

import (
    "sync"
    "time"
)

func waitTimeout(wg *sync.WaitGroup, timeout time.Duration) bool {
    c := make(chan struct{})
    go func() {
        wg.Wait()
        close(c)
    }()
    select {
    case <-c:
        return false // completed normally
    case <-time.After(timeout):
        return true // timed out
    }
}
  • Un canal (c) est créé pour signaler quand le groupe d'attente termine son attente.
  • Une goroutine est générée pour appeler wg.Wait() et fermer le canal une fois terminé.
  • Une instruction select écoute soit le canal soit fermé, soit un délai d'attente.
  • Si le canal est fermé, la fonction renvoie false, indiquant un achèvement normal.
  • Si le le délai d'attente est atteint, la fonction renvoie vrai, ce qui signifie un délai d'attente.

Simplification de la solution recommandée

Pour une implémentation plus simple, considérez ce qui suit :

  • Fermez le canal pour signaler l'achèvement au lieu d'envoyer une valeur.
  • Utilisez defer pour fermer le canal même si la fonction se termine prématurément.
  • Supprimez le groupe d'attente si une seule tâche doit être attendue .
  • Utilisez des durées directement sans conversions (par exemple, time.Second).

Approche alternative : utiliser un contexte annulable

Une approche alternative consiste à utiliser un contexte annulable contexte :

import (
    "context"
    "sync/atomic"
    "sync"
)

func waitWithCancel(ctx context.Context, wg *sync.WaitGroup) bool {
    ctxDone := make(chan struct{})
    var exited int32
    go func() {
        defer close(ctxDone)
        wg.Wait()
        atomic.StoreInt32(&exited, 1)
    }()

    select {
    case <-ctx.Done():
        return atomic.LoadInt32(&exited) == 0
    case <-ctxDone:
        return true
    }
}
  • Un contexte annulable (ctx) est créé.
  • Un canal (ctxDone) est utilisé pour signaler lorsque le contexte est annulé.
  • Une goroutine est générée pour attendre le groupe d'attente et signaler le canal ctxDone.
  • Une instruction select écoute soit le contexte à annuler, soit le groupe d'attente à terminer.
  • Si le contexte est annulée, la fonction revient selon que le groupe d'attente a déjà terminé son attente.

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