英文:
How timers work in Golang
问题
我正在尝试理解Go语言中的通道。这是一个简单的代码示例:
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
i := 0
for {
select {
case <-time.After(3 * time.Second):
fmt.Println("EXIT: 3 seconds")
return
case <-time.After(1 * time.Second):
fmt.Println(i, "second")
}
i++
}
}()
wg.Wait()
}
我期望控制台输出结果如下:
0 second
1 second
2 second
EXIT: 3 seconds
但实际上输出结果是这样的:
0 second
1 second
2 second
3 second
4 second
5 second
6 second
...
我错过了什么关于这个计时器的问题,我该如何解决这个问题?
英文:
I'm trying to undersand channels in Go. There is a simple code
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
i := 0
for {
select {
case <-time.After(3 * time.Second):
fmt.Println("EXIT: 3 seconds")
return
case <-time.After(1 * time.Second):
fmt.Println(i, "second")
}
i++
}
}()
wg.Wait()
}
I expect console result like this
0 second
1 second
2 second
EXIT: 3 seconds
But actually it is like this
0 second
1 second
2 second
3 second
4 second
5 second
6 second
...
What am I missing with this timer and how can I fix a problem?
答案1
得分: 3
这是因为使用了for循环。循环中的每一次迭代,select
语句中的case <-time.After(3 * time.Second)
会被重新评估并生成一个新的计时器。例如,按照以下方式进行操作,事情应该能够正常工作:
stop := time.After(3 * time.Second)
for {
select {
case <-stop:
fmt.Println("退出:3秒")
return
case <-time.After(1 * time.Second):
fmt.Println(i, "秒")
}
}
英文:
It's because of for loop. Each circle of loop RightHandSide of case <-time.After(3 * time.Second):
in select
statement evaluated and give you fresh timer. For example this way things should work
stop := time.After(3 * time.Second)
for {
select {
case <-stop:
fmt.Println("EXIT: 3 seconds")
return
case <-time.After(1 * time.Second):
fmt.Println(i, "second")
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论