


Warum schlägt Timeout in Go-Kanälen fehl, wenn Goroutinen verwendet werden?
Nov 09, 2024 am 12:21 AMTimeouts 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"})) }
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"})) }
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"})) }
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!

Heißer Artikel

Hot-Tools-Tags

Heißer Artikel

Heiße Artikel -Tags

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen

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 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 benutzerdefinierte Typ -Einschränkungen für Generika in Go definieren?

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 schreibe ich Benchmarks, die die reale Leistung in Go genau widerspiegeln?
