Heim >Backend-Entwicklung >Golang >Go-Kanäle: Warum wird mein Timeout in einer „select'-Anweisung nie ausgelöst?
Go-Kanäle: Warum Zeitüberschreitungen nicht ausgeführt werden
Stellen Sie sich ein Szenario vor, in dem Goroutinen und Kanäle wie im folgenden Codeausschnitt verwendet werden. Warum tritt das Timeout-Szenario nie ein?
func main() { c1 := make(chan int, 1) go func() { for { time.Sleep(1500 * time.Millisecond) c1 <- 10 } }() go func() { for { select { case i := <-c1: fmt.Println(i) case <-time.After(2000 * time.Millisecond): fmt.Println("TIMEOUT") // Not Executed } } }() fmt.Scanln() }
Analyse
Das Timeout-Szenario tritt nicht ein, da eine Goroutine kontinuierlich etwa alle 1,5 Sekunden Werte an den c1-Kanal sendet . Das Timeout würde nur wirksam, wenn 2 Sekunden lang keine Werte von c1 empfangen würden.
Bei Empfang eines Werts von c1 wird jedoch ein neuer Time.After-Aufruf in der anschließenden Select-Ausführung durchgeführt, wodurch ein neuer Kanal generiert wird wobei ein Wert erst nach weiteren 2 Sekunden ausgegeben wird. Der Timeout-Kanal aus der vorherigen Select-Ausführung wird verworfen, wodurch er unwirksam wird.
Lösung
Um dieses Problem zu beheben, sollte der Timeout-Kanal nur einmal erstellt werden, und zwar effektiv:
timeout := time.After(2000 * time.Millisecond) for { select { case i := <-c1: fmt.Println(i) case <-timeout: fmt.Println("TIMEOUT") // Will be printed after 2 seconds } }
Ausgabe
Der geänderte Code anschließend druckt:
10 TIMEOUT 10 10 10 ...
Daher wird das Timeout-Szenario nun nach 2 Sekunden erfolgreich ausgeführt und spiegelt das beabsichtigte Verhalten wider.
Das obige ist der detaillierte Inhalt vonGo-Kanäle: Warum wird mein Timeout in einer „select'-Anweisung nie ausgelöst?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!