Heim >Backend-Entwicklung >Golang >Go-Kanäle: Warum wird mein Timeout in einer „select'-Anweisung nie ausgelöst?

Go-Kanäle: Warum wird mein Timeout in einer „select'-Anweisung nie ausgelöst?

DDD
DDDOriginal
2024-12-26 03:37:09401Durchsuche

Go Channels: Why Doesn't My Timeout in a `select` Statement Ever Trigger?

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!

Stellungnahme:
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