Maison  >  Article  >  développement back-end  >  Pourquoi mon délai d'attente Go ne fonctionne-t-il pas dans cet exemple de canal ?

Pourquoi mon délai d'attente Go ne fonctionne-t-il pas dans cet exemple de canal ?

DDD
DDDoriginal
2024-11-08 17:48:02677parcourir

Why Does My Go Timeout Not Work in this Channel Example?

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

Dans Go, les délais d'attente et les canaux offrent un moyen pratique de contrôler l'exécution des goroutines et de synchroniser leurs résultats . Cependant, il existe certains scénarios dans lesquels le cas d'expiration peut ne pas s'exécuter comme prévu.

Énoncé du problème

Considérez le code Go 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"}))
}

Le but de ce code est de vérifier si toutes les URL de la liste fournie sont accessibles. Si une URL ne répond pas dans la seconde, la fonction doit renvoyer false.

Cependant, lors de l'exécution de ce code, elle retournera toujours true. Le cas de délai d'attente n'est pas exécuté.

Explication

Le problème survient en raison de la manière dont check(u) est exécuté. Dans la fonction IsReachable, chaque goroutine vérifie l'accessibilité d'une URL en appelant check(u). Cependant, check(u) dort pendant 4 secondes dans la goroutine actuelle avant de revenir.

Dans l'instruction select, le cas ch <- check(u): branch est le premier à devenir disponible, car check( u) est déjà revenu. Cela empêche le cas d'expiration de s'exécuter, ce qui fait que la fonction renvoie toujours vrai.

Solution

Pour résoudre ce problème, la fonction check(u) doit être exécutée dans un goroutine séparé. Cela permet à l'instruction select de gérer correctement le cas d'expiration.

Voici le code mis à jour :

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"}))
}

Maintenant, si l'une des URL ne répond pas dans la seconde, la fonction retournera FAUX. De plus, si une seule URL est disponible, la fonction retournera vrai.

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