Maison > Article > développement back-end > Pourquoi mon délai d'attente Go ne fonctionne-t-il pas dans cet exemple de canal ?
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!