Inhaltsverzeichnis
Timeouts mit Kanälen in Go verwenden
Heim Backend-Entwicklung Golang Warum schlägt Timeout in Go-Kanälen fehl, wenn Goroutinen verwendet werden?

Warum schlägt Timeout in Go-Kanälen fehl, wenn Goroutinen verwendet werden?

Nov 09, 2024 am 12:21 AM

Why Does Timeout Fail in Go Channels When Using Goroutines?

Timeouts mit Kanälen in Go verwenden

Im Bereich der gleichzeitigen Programmierung spielen Goroutinen und Kanäle eine zentrale Rolle bei der Implementierung asynchroner Kommunikationsmuster. Es kann jedoch etwas schwierig sein, zu verstehen, wie sie mit Zeitüberschreitungen interagieren.

Bedenken Sie den folgenden Codeausschnitt:

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, festzustellen, ob eine Liste von URLs erreichbar ist . Es wird jedoch immer true zurückgegeben, unabhängig davon, ob eine URL nicht erreichbar ist. Warum wird der Timeout-Fall nicht ausgeführt?

Der Schlüssel zum Verständnis dieses Problems liegt in der Interaktion von Goroutinen und Kanälen. Wenn check(u) in der äußeren Goroutine aufgerufen wird, wird die Ausführung dieser Goroutine für 4 Sekunden angehalten. Die Select-Anweisung wird jedoch erst ausgeführt, wenn check(u) zurückkehrt. Zu diesem Zeitpunkt sind sowohl check(u) als auch time.After-Zweige betriebsbereit.

Um dieses Problem zu beheben, müssen wir check(u) innerhalb seiner eigenen Goroutine isolieren:

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

In diesem überarbeiteten Code wird check(u) in einer separaten Goroutine aufgerufen. Dadurch kann die Select-Anweisung richtig zwischen dem Abschluss von check(u) und der Timeout-Bedingung unterscheiden.

Alternativ könnten wir den Code vereinfachen, indem wir ein einziges Timeout für alle URLs verwenden:

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

In dieser Version verwenden wir einen Kanal, der alle Antworten speichern kann. Ein Timeout wird auf eine Sekunde festgelegt und das erste Ergebnis, das im Kanal ankommt, wird zurückgegeben. Wenn keine der URLs vor Ablauf des Timeouts erreichbar ist, erhält der Kanal einen falschen Wert.

Das obige ist der detaillierte Inhalt vonWarum schlägt Timeout in Go-Kanälen fehl, wenn Goroutinen verwendet werden?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

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

Heiße Artikel -Tags

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

GO Language Pack Import: Was ist der Unterschied zwischen Unterstrich und ohne Unterstrich? GO Language Pack Import: Was ist der Unterschied zwischen Unterstrich und ohne Unterstrich? Mar 03, 2025 pm 05:17 PM

GO Language Pack Import: Was ist der Unterschied zwischen Unterstrich und ohne Unterstrich?

Wie kann ich kurzfristige Informationsübertragung zwischen Seiten im BeEGO-Framework implementieren? Wie kann ich kurzfristige Informationsübertragung zwischen Seiten im BeEGO-Framework implementieren? Mar 03, 2025 pm 05:22 PM

Wie kann ich kurzfristige Informationsübertragung zwischen Seiten im BeEGO-Framework implementieren?

Wie schreibe ich Scheinobjekte und Stubs zum Testen in Go? Wie schreibe ich Scheinobjekte und Stubs zum Testen in Go? Mar 10, 2025 pm 05:38 PM

Wie schreibe ich Scheinobjekte und Stubs zum Testen in Go?

Wie kann ich Tracing -Tools verwenden, um den Ausführungsfluss meiner GO -Anwendungen zu verstehen? Wie kann ich Tracing -Tools verwenden, um den Ausführungsfluss meiner GO -Anwendungen zu verstehen? Mar 10, 2025 pm 05:36 PM

Wie kann ich Tracing -Tools verwenden, um den Ausführungsfluss meiner GO -Anwendungen zu verstehen?

Wie kann ich benutzerdefinierte Typ -Einschränkungen für Generika in Go definieren? Wie kann ich benutzerdefinierte Typ -Einschränkungen für Generika in Go definieren? Mar 10, 2025 pm 03:20 PM

Wie kann ich benutzerdefinierte Typ -Einschränkungen für Generika in Go definieren?

Wie schreibe ich Dateien in Go Language bequem? Wie schreibe ich Dateien in Go Language bequem? Mar 03, 2025 pm 05:15 PM

Wie schreibe ich Dateien in Go Language bequem?

Wie konvertieren Sie die Liste der MySQL -Abfrageergebnisse in eine benutzerdefinierte Struktur -Slice in Go -Sprache? Wie konvertieren Sie die Liste der MySQL -Abfrageergebnisse in eine benutzerdefinierte Struktur -Slice in Go -Sprache? Mar 03, 2025 pm 05:18 PM

Wie konvertieren Sie die Liste der MySQL -Abfrageergebnisse in eine benutzerdefinierte Struktur -Slice in Go -Sprache?

Wie schreibe ich Benchmarks, die die reale Leistung in Go genau widerspiegeln? Wie schreibe ich Benchmarks, die die reale Leistung in Go genau widerspiegeln? Mar 10, 2025 pm 05:36 PM

Wie schreibe ich Benchmarks, die die reale Leistung in Go genau widerspiegeln?

See all articles