为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
千巷猫影 2022-01-17 16:35:13
我有一个正在监听 2 个频道、一个自动收报机和一个计时器的选择块:package mainimport (    "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!")        }    }}如果我运行代码,time.After案例永远不会运行,但自动收报机工作正常。如果我删除代码,time.After正确触发:package mainimport (    "fmt"    "time")func main() {    for {        select {        case <-time.After(12 * time.Second):            fmt.Println("12 seconds elapsed!")        }    }}如果我使用计时器而不是time.After:package mainimport (    "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!")        }    }}为什么会这样?
查看完整描述

2 回答

?
白猪掌柜的

TA贡献1893条经验 获得超10个赞

Aselect阻塞,直到它的一个案例准备好,然后它执行那个案例。在您的示例中 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!")

        }

    }

}

您可以通过在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!")

                }   

        }   

}   


查看完整回答
反对 回复 2022-01-17
?
拉丁的传说

TA贡献1789条经验 获得超8个赞

关键是,当调用 select 时,它将在所有 case 子句中重新创建通道。如果您在 中创建计时器case <- newCreateTimerChannel,它将启动一个新计时器。所以把定时器的创建放在for循环之外,让它成为一个全局定时器。


查看完整回答
反对 回复 2022-01-17
  • 2 回答
  • 0 关注
  • 181 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号