Maison  >  Article  >  développement back-end  >  Comment implémenter correctement les délais d'attente dans Go Goroutines avec les canaux ?

Comment implémenter correctement les délais d'attente dans Go Goroutines avec les canaux ?

DDD
DDDoriginal
2024-11-08 14:57:02258parcourir

How to Implement Timeouts Correctly in Go Goroutines with Channels?

Utilisation des délais d'attente avec les canaux dans Go

Les goroutines et les canaux fournissent un mécanisme puissant pour la programmation simultanée dans Go. Cependant, la gestion des délais d'attente dans les goroutines peut être délicate.

Dans un scénario où vous souhaitez vérifier l'accessibilité d'une liste d'URL à l'aide de goroutines et d'un délai d'attente, il peut y avoir des situations où le délai d'attente n'est pas exécuté même si certaines URL ne sont pas accessibles.

Analysons le code fourni :

func check(u string) bool {
    time.Sleep(4 * time.Second)
    return true
}

func IsReachable(urls []string) bool {
    ch := make(chan bool, 1)
    for _, url := range urls {
        go func(u string) {
            select {
            case ch <- check(u):
            case <-time.After(time.Second):
                ch <- false
            }
        }(url)
    }
    return <-ch
}

Le problème réside dans la fonction de vérification. Lorsque vous utilisez time.Sleep dans une goroutine, cela met en pause la goroutine actuelle, qui dans ce cas est la goroutine exécutant la fonction de vérification. Pendant que la fonction de vérification est en pause, l'instruction select dans la goroutine externe tentera toujours de s'exécuter.

Dans ce cas, les deux branches de l'instruction select (vérifiant le résultat ou le délai d'attente) seront exécutables après 4 secondes lorsque le chèque revient. Cependant, comme les deux branches sont exécutables, le moteur d'exécution peut choisir d'exécuter l'une ou l'autre, ce qui peut toujours renvoyer vrai.

Pour résoudre ce problème, vous devez créer une nouvelle goroutine pour chaque fonction de vérification, comme indiqué dans le code corrigé ci-dessous :

func check(u string, checked chan<- bool) {
    time.Sleep(4 * time.Second)
    checked <- true
}

func IsReachable(urls []string) bool {
    ch := make(chan bool, 1)
    for _, url := range urls {
        go func(u string) {
            checked := make(chan bool)
            go check(u, checked)
            select {
            case ret := <-checked:
                ch <- ret
            case <-time.After(time.Second):
                ch <- false
            }
        }(url)
    }
    return <-ch
}

Dans ce cas, la fonction de vérification est exécutée dans une goroutine séparée, garantissant qu'elle ne met pas en pause la goroutine externe et que le délai d'attente peut être correctement exécuté.

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