Warum funktioniert mein Go-Timeout in diesem Kanalbeispiel nicht?

DDD
Freigeben: 2024-11-08 17:48:02
Original
685 Leute haben es durchsucht

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

Go: Timeouts mit Kanälen verwenden

In Go bieten Timeouts und Kanäle eine bequeme Möglichkeit, die Ausführung von Goroutinen zu steuern und ihre Ergebnisse zu synchronisieren . Es gibt jedoch bestimmte Szenarien, in denen der Timeout-Fall möglicherweise nicht wie erwartet ausgeführt wird.

Problembeschreibung

Beachten Sie den folgenden Go-Code:

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"}))
}
Nach dem Login kopieren

Das Ziel dieses Codes besteht darin, zu überprüfen, ob alle URLs in der bereitgestellten Liste erreichbar sind. Wenn eine URL nicht innerhalb einer Sekunde antwortet, sollte die Funktion „false“ zurückgeben.

Bei der Ausführung dieses Codes wird jedoch immer „true“ zurückgegeben. Der Timeout-Fall wird nicht ausgeführt.

Erklärung

Das Problem entsteht durch die Art und Weise, wie check(u) ausgeführt wird. In der IsReachable-Funktion prüft jede Goroutine die Erreichbarkeit einer URL, indem sie check(u) aufruft. check(u) schläft jedoch 4 Sekunden lang in der aktuellen Goroutine, bevor es zurückkehrt.

Innerhalb der select-Anweisung ist der case ch <- check(u): Branch der erste, der verfügbar wird, da check( u) ist bereits zurückgekehrt. Dies verhindert, dass der Timeout-Fall jemals ausgeführt wird, was dazu führt, dass die Funktion immer „true“ zurückgibt.

Lösung

Um dieses Problem zu beheben, sollte die Funktion check(u) ausgeführt werden in einer separaten Goroutine. Dadurch kann die Select-Anweisung den Timeout-Fall ordnungsgemäß behandeln.

Hier ist der aktualisierte Code:

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"}))
}
Nach dem Login kopieren

Wenn nun eine der URLs nicht innerhalb einer Sekunde antwortet, kehrt die Funktion zurück FALSCH. Wenn nur eine URL verfügbar ist, gibt die Funktion außerdem true zurück.

Das obige ist der detaillierte Inhalt vonWarum funktioniert mein Go-Timeout in diesem Kanalbeispiel nicht?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!