Go 如果在计时器通道过期后再次尝试从其接收,会发生什么情况

Go 如果在计时器通道过期后再次尝试从其接收,会发生什么情况,go,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.Pri

我正在玩围棋教程中的一个。我对代码进行了如下编辑:

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:=time.After(500*time.毫秒)
将返回一个频道,并在500毫秒后向该频道发送一条消息。现在让我们考虑您的代码:

case <-boom:
   fmt.Println("BOOM!")
   c, ok := <-boom
   fmt.Println(c)
   fmt.Println(ok)
它接收消息,打印boom,然后返回(结束程序)。如果你想让你的代码到达它输出“finnished”的位置,那么你需要下面的代码。请注意,需要标签
循环

终止最里面的“for”、“switch”或“select”的执行

因此,如果没有标签中断,将退出select,但for循环将继续

package main

import (
    "fmt"
    "time"
)

func main() {
    tick := time.Tick(100 * time.Millisecond)
    boom := time.After(500 * time.Millisecond)
loop:
    for {
        select {
        case <-tick:
            fmt.Println("tick.")
        case <-boom:
            fmt.Println("BOOM!")
            break loop
        default:
            fmt.Println("    .")
            time.Sleep(50 * time.Millisecond)
        }
    }
    fmt.Println("Finished")
}
主程序包
进口(
“fmt”
“时间”
)
func main(){
滴答声:=时间滴答声(100*时间毫秒)
动臂:=时间后(500*时间毫秒)
循环:
为了{
挑选{

case
c
ok
从不打印,因为从来没有通过
boom
频道发送过任何其他内容。这是非常直接的。你是否有其他想法?如果你想重用它,你必须使用它。@Flimzy但在这种情况下不会永远收到block?程序如何终止?我不理解你的问题。正如我所说的是的,你的接收永远被阻塞,因为没有任何东西被发送。让我困惑的是程序确实终止了。或者至少当我在围棋场运行它时它终止了(你可以复制/粘贴我的代码并自己尝试一下?)。据我所知,它不应该终止,这就是为什么我对它退出围棋场感到困惑的原因“程序已退出:进程花费的时间太长。”。这是因为go Playway在沙箱中运行应用程序,这限制了执行时间(除其他外)。如果没有此选项,则有人将使用它来挖掘比特币:-)。尝试在您的计算机上运行它,它将不会退出。真的吗?对我来说,它在go Playder中退出时不会出现任何错误:/I在运行时,我将您的代码复制/粘贴到Playder中,这会导致“程序退出:进程耗时太长”
package main

import (
    "fmt"
    "time"
)

func main() {
    tick := time.Tick(100 * time.Millisecond)
    boom := time.After(500 * time.Millisecond)
loop:
    for {
        select {
        case <-tick:
            fmt.Println("tick.")
        case <-boom:
            fmt.Println("BOOM!")
            break loop
        default:
            fmt.Println("    .")
            time.Sleep(50 * time.Millisecond)
        }
    }
    fmt.Println("Finished")
}