Gestion des délais d'attente avec les chaînes dans Go
Problème :
Lors de l'utilisation de goroutines et de chaînes pour vérifiez l'accessibilité d'une liste d'URL, la condition de timeout ne semble pas être exécutée. Cela fait que le code renvoie toujours vrai, même si certaines URL sont inaccessibles.
Analyse :
Le problème réside dans l'implémentation de la fonction check(u), qui fait que le délai d'attente ne sera jamais exécuté. Dans votre code, la fonction check(u) s'exécute dans la goroutine actuelle, bloquant l'exécution de l'instruction select dans IsReachable. Au moment où l'instruction select est débloquée, les canaux check(u) et time.After(time.Second) sont prêts à être consommés et le runtime peut choisir l'un ou l'autre.
Solution 1 :
Pour résoudre ce problème, vous pouvez exécuter la fonction check(u) dans un fichier séparé goroutine :
package main 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"})) }
Dans ce code modifié, la fonction check(u) est exécutée dans une goroutine et le résultat est transmis au canal vérifié. L'instruction select dans IsReachable attend désormais que le canal coché ou le canal d'expiration soit prêt. Cela garantit que la condition de délai d'attente est correctement gérée.
Solution 2 :
Vous pouvez également simplifier le code en définissant un délai d'attente unique pour toutes les URL. Cette approche est réalisable si le délai d'attente est suffisamment long par rapport au temps nécessaire pour créer des goroutines :
package main 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"})) }
Dans ce code, un seul délai d'attente est défini pour toutes les URL utilisant time.AfterFunc. Si une URL est accessible dans le délai d'expiration, le canal ch recevra true et la fonction retournera true. Sinon, false sera envoyé à ch et la fonction retournera false.
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!