Wie implementiert man Timeouts in Go-Goroutinen mit Kanälen richtig?

DDD
Freigeben: 2024-11-08 14:57:02
Original
291 Leute haben es durchsucht

How to Implement Timeouts Correctly in Go Goroutines with Channels?

Timeouts mit Kanälen in Go verwenden

Goroutinen und Kanäle bieten einen leistungsstarken Mechanismus für die gleichzeitige Programmierung in Go. Der Umgang mit Zeitüberschreitungen in Goroutinen kann jedoch schwierig sein.

In einem Szenario, in dem Sie die Erreichbarkeit einer Liste von URLs mithilfe von Goroutinen und einer Zeitüberschreitung überprüfen möchten, kann es Situationen geben, in denen die Zeitüberschreitung nicht ausgeführt wird, selbst wenn Einige der URLs sind nicht erreichbar.

Lassen Sie uns den bereitgestellten Code analysieren:

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

Das Problem liegt in der Funktion prüfen. Wenn Sie time.Sleep in einer Goroutine verwenden, wird die aktuelle Goroutine angehalten, in diesem Fall die Goroutine, die die Prüffunktion ausführt. Während die Prüffunktion angehalten ist, versucht die Select-Anweisung in der äußeren Goroutine weiterhin auszuführen.

In diesem Fall sind beide Zweige der Select-Anweisung (Überprüfung des Ergebnisses oder der Zeitüberschreitung) nach 4 ausführbar Sekunden, wenn der Scheck zurückgegeben wird. Da jedoch beide Zweige ausführbar sind, kann die Laufzeit einen von beiden ausführen, was dazu führen kann, dass immer „true“ zurückgegeben wird.

Um dieses Problem zu lösen, müssen Sie für jede Prüffunktion eine neue Goroutine erstellen, wie in gezeigt der korrigierte Code unten:

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(time.Second):
                ch <- false
            }
        }(url)
    }
    return <-ch
}
Nach dem Login kopieren

In diesem Fall wird die Prüffunktion in einer separaten Goroutine ausgeführt, um sicherzustellen, dass sie die äußere Goroutine nicht anhält und das Timeout korrekt sein kann ausgeführt.

Das obige ist der detaillierte Inhalt vonWie implementiert man Timeouts in Go-Goroutinen mit Kanälen richtig?. 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