为什么 time.After 在与 select 块中的代码配对时永远不会触发?
Why does time.After never fire when it is paired with a ticker in a select block?
我有一个 select 块正在监听 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!")
}
}
}
为什么会这样?
A select
阻塞直到它的一个 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!")
}
}
}
您可以通过在 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!")
}
}
}
关键是,当调用select时,它会在所有情况下重新创建通道子句。如果您在 case <- newCreateTimerChannel
中创建一个计时器,它将启动一个新的计时器。所以把定时器的创建放在for循环之外,让它成为一个全局定时器。
我有一个 select 块正在监听 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!")
}
}
}
为什么会这样?
A select
阻塞直到它的一个 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!")
}
}
}
您可以通过在 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!")
}
}
}
关键是,当调用select时,它会在所有情况下重新创建通道子句。如果您在 case <- newCreateTimerChannel
中创建一个计时器,它将启动一个新的计时器。所以把定时器的创建放在for循环之外,让它成为一个全局定时器。