为什么 time.After 与选择块中的股票代码配对时永远不会触发?

F21*_*F21 2 timer go ticker

我有一个选择块,它正在收听 2 个频道、一个自动收报机和一个计时器:

package main

import (
    "fmt"
    "time"
)

func main() {

    ticker := time.NewTicker(5 * time.Second)
    for {
        select {
        case z := <-ticker.C:
            fmt.Printf("tick %d\n", z)

        case <-time.After(12 * time.Second):
            fmt.Println("12 seconds elapsed!")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我运行代码,time.After案例永远不会运行,但自动收报机工作正常。

如果我删除自动收报机,time.After则会正确触发:

package main

import (
    "fmt"
    "time"
)

func main() {

    for {
        select {
        case <-time.After(12 * time.Second):
            fmt.Println("12 seconds elapsed!")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我使用计时器而不是time.After

package main

import (
    "fmt"
    "time"
)

func main() {

    ticker := time.NewTicker(5 * time.Second)
    timer := time.NewTimer(12 * time.Second)
    for {
        select {
        case z := <-ticker.C:
            fmt.Printf("tick %d\n", z)

        case <-timer.C:
            fmt.Println("12 seconds elapsed!")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么会发生这种情况?

Pra*_*til 8

Aselect阻塞直到它的一个 case 准备好,然后它执行那个 case。在您的示例中 time.After() 永远不会被调用。

func main() {

    ticker := time.NewTicker(5 * time.Second)
    for {
        select {
        case z := <-ticker.C:
            fmt.Printf("tick %d\n", z)

        //This never gets chance to be ready. It'll work if you make it less than 5 seconds.
        case <-time.After(12 * time.Second): 
            fmt.Println("12 seconds elapsed!")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以通过在for循环之前声明计时器来使其工作。

func main() {

        ticker := time.NewTicker(5 * time.Second)
        timer := time.After(12 * time.Second)
        for {
                select {
                case z := <-ticker.C:
                        fmt.Printf("tick %d\n", z)

                case <-timer:
                        fmt.Println("12 seconds elapsed!")
                }   
        }   
}   
Run Code Online (Sandbox Code Playgroud)