猿问

如果您在 Timer 频道过期后再次尝试从该频道接收会发生什么

我正在玩 Tour of Go 教程中的一个示例。我已将代码编辑如下:


package main


import (

    "fmt"

    "time"

)


func main() {

    tick := time.Tick(100 * time.Millisecond)

    boom := time.After(500 * time.Millisecond)

    for {

        select {

        case <-tick:

            fmt.Println("tick.")

        case <-boom:

            fmt.Println("BOOM!")

            c, ok := <-boom

            fmt.Println(c)

            fmt.Println(ok)

        default:

            fmt.Println("    .")

            time.Sleep(50 * time.Millisecond)

        }

    }

    fmt.Println("Finished")

}

但是,代码的输出如下:


    .

    .

tick.

    .

    .

tick.

    .

    .

tick.

    .

    .

tick.

    .

    .

tick.

BOOM!

c并且ok永远不会打印,最后一个“完成”也永远不会打印。boom有人可以帮助我了解当我第二次尝试从频道接收时到底发生了什么?


守着一只汪
浏览 125回答 1
1回答

慕标琳琳

考虑 time.After 做了什么(引用go docs):After 等待持续时间过去,然后在返回的通道上发送当前时间。所以boom := time.After(500 * time.Millisecond)将返回一个通道并在 500 毫秒后向该通道发送一条消息。现在让我们考虑您的代码:case <-boom:&nbsp; &nbsp;fmt.Println("BOOM!")&nbsp; &nbsp;c, ok := <-boom&nbsp; &nbsp;fmt.Println(c)&nbsp; &nbsp;fmt.Println(ok)当在景气通道上接收到某些内容时,您的代码会打印“景气”,然后在景气通道上等待其他内容。但是,只有一件事会发送到繁荣通道,因此该语句c, ok := <-boom将永远不会完成(并且您的应用程序将永远不会终止)。如果您将繁荣从 a 更改为time.Aftera,time.Tick那么您可能会看到更像您期望的东西(应用程序仍将永远运行)。原始代码有点不同:case <-boom:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("BOOM!")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return它接收消息,打印繁荣然后返回(结束程序)。如果您希望您的代码到达它输出“finished”的位置,那么您需要类似于下面的代码。请注意,标签loop是必需的,因为 break:终止执行最里面的“for”、“switch”或“select”所以没有标签 break 将退出选择,但 for 循环将继续。package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "time")func main() {&nbsp; &nbsp; tick := time.Tick(100 * time.Millisecond)&nbsp; &nbsp; boom := time.After(500 * time.Millisecond)loop:&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; case <-tick:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("tick.")&nbsp; &nbsp; &nbsp; &nbsp; case <-boom:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("BOOM!")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break loop&nbsp; &nbsp; &nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("&nbsp; &nbsp; .")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; time.Sleep(50 * time.Millisecond)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Println("Finished")}
随时随地看视频慕课网APP

相关分类

Go
我要回答