我有一个正在监听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!")
}
}
}
如果我运行代码,time.After
案例永远不会运行,但代码工作正常。
如果我删除了代码,time.After
会正确触发:
package main
import (
"fmt"
"time"
)
func main() {
for {
select {
case <-time.After(12 * time.Second):
fmt.Println("12 seconds elapsed!")
}
}
}
如果我使用计时器而不是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!")
}
}
}
为什么会这样?
答案 0 :(得分:4)
select
阻塞直到其中一个案例准备就绪,然后执行该案例。在你的例子中.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!")
}
}
}
答案 1 :(得分:1)
关键是,当调用select时,它将在所有case子句中重新创建通道。如果您在case <- newCreateTimerChannel
中创建一个计时器,它将启动一个新计时器。因此,将计时器创建内容置于for循环之外,以使其成为全局计时器。