Maison > développement back-end > Golang > le corps du texte

Pourquoi le délai d'attente échoue-t-il dans les canaux Go lors de l'utilisation de Goroutines ?

Mary-Kate Olsen
Libérer: 2024-11-09 00:21:01
original
751 Les gens l'ont consulté

Why Does Timeout Fail in Go Channels When Using Goroutines?

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

Dans le domaine de la programmation simultanée, les Goroutines et les canaux jouent un rôle central dans la mise en œuvre de modèles de communication asynchrones. Cependant, comprendre comment ils interagissent avec les délais d'attente peut être un peu délicat.

Considérez l'extrait de code suivant :

import "fmt"
import "time"

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
}

func main() {
    fmt.Println(IsReachable([]string{"url1"}))
}
Copier après la connexion

L'objectif de ce code est de déterminer si une liste d'URL est accessible. . Cependant, il renvoie toujours vrai, qu'une URL soit inaccessible ou non. Pourquoi le cas de délai d'attente n'est-il pas exécuté ?

La clé pour comprendre ce problème réside dans la façon dont les Goroutines et les canaux interagissent. Lorsque check(u) est appelé dans le Goroutine externe, il suspend l'exécution de ce Goroutine pendant 4 secondes. Cependant, l'instruction select ne s'exécute qu'une fois check(u) renvoyé. À ce moment-là, les branches check(u) et time.After sont prêtes à être exécutées.

Pour résoudre ce problème, nous devons isoler check(u) dans sa propre Goroutine :

import "fmt"
import "time"

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(1 * time.Second):
                ch <- false
            }
        }(url)
    }
    return <-ch
}

func main() {
    fmt.Println(IsReachable([]string{"url1"}))
}
Copier après la connexion

Dans ce code révisé, check(u) est invoqué dans un Goroutine distinct. Cela permet à l'instruction select de faire la distinction correctement entre l'achèvement de check(u) et la condition d'expiration.

Alternativement, nous pourrions simplifier le code en utilisant un seul délai d'attente pour toutes les URL :

import "fmt"
import "time"

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

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

func main() {
    fmt.Println(IsReachable([]string{"url1", "url2"}))
}
Copier après la connexion

Dans cette version, nous utilisons un canal qui peut contenir toutes les réponses. Un délai d'attente est fixé à une seconde et le premier résultat arrivant dans le canal est renvoyé. Si aucune des URL n'est accessible avant l'expiration du délai d'attente, la chaîne recevra une fausse valeur.

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!

source:php.cn
Déclaration de ce site Web
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
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal