Go 使用Timer.Reset()的计时器示例未按所述工作
我一直在使用示例,试图让我的第一个“go例程”运行,但当我让它运行时,它将无法按照go文档中关于timer.Reset()函数的规定工作Go 使用Timer.Reset()的计时器示例未按所述工作,go,timer,channels,routines,Go,Timer,Channels,Routines,我一直在使用示例,试图让我的第一个“go例程”运行,但当我让它运行时,它将无法按照go文档中关于timer.Reset()函数的规定工作 在我的情况下,我相信我这样做是很好的,因为我不在乎缓冲区中有什么,如果有的话。这一切都是为了触发case您创建了一个计时器并立即停止它: var tmr = time.NewTimer(time.Second) tmr.Stop() 这没有任何意义,我想这只是你的“意外” 但更进一步,在你的循环中: case _, ok := <-watche
在我的情况下,我相信我这样做是很好的,因为我不在乎缓冲区中有什么,如果有的话。这一切都是为了触发
case您创建了一个计时器并立即停止它:
var tmr = time.NewTimer(time.Second)
tmr.Stop()
这没有任何意义,我想这只是你的“意外”
但更进一步,在你的循环中:
case _, ok := <-watcher.Events:
case\ux,ok:=您使用time.Timer时未命中
试试这样简单的东西
package main
import (
"fmt"
"log"
"time"
)
func main() {
timer := time.NewTimer(time.Second)
watcher := make(chan bool)
done := make(chan bool)
evs := make(chan bool)
go func() {
trigger := false
for {
select {
case <-timer.C:
if trigger {
trigger = false
evs <- true
}
timer.Reset(time.Second)
case _, ok := <-watcher:
if !ok {
return
}
trigger = true
case <-done:
fmt.Println(`DONE TRIGGERED`)
return
}
}
}()
go func() {
for e := range evs {
log.Println("e", e)
}
}()
// simulate multiple events
watcher <- true
watcher <- true
watcher <- true
watcher <- true
<-time.After(time.Second + time.Millisecond*100)
watcher <- true
watcher <- true
watcher <- true
<-time.After(time.Second + time.Millisecond*100)
fmt.Println("Hello, playground")
}
主程序包
进口(
“fmt”
“日志”
“时间”
)
func main(){
计时器:=time.NewTimer(time.Second)
观察者:=制造(chan bool)
完成:=制作(陈波)
电动汽车:=制造(chan bool)
go func(){
触发器:=假
为了{
挑选{
案例除了什么(q.v.),请注意
例如,假设该计划尚未收到t.C.的通知:
if !t.Stop() {
<-t.C
}
是一个更好的例子。它执行一次非阻塞尝试,如果存在,将消耗计时器滴答声,如果没有计时器滴答声,则不会执行任何操作。无论调用t.Stop
时计时器是否实际运行,这都会起作用。实际上,如果t.Stop
返回true
,即使在这种情况下,t.Stop
停止了计时器,因此计时器从未设法将计时器滴答声放入通道中。(因此,如果通道中有数据,则必须是以前清除通道失败留下的数据。如果没有此类错误,则无需尝试接收。)
但是,如果其他人或其他goroutine正在或可能正在阅读该频道,您根本不应该这样做。尽管调用了Stop
,但无法知道谁(您或他们)将在该频道中收到任何计时器滴答声
同时,如果你不打算进一步使用计时器,在通道中留下一个计时器滴答声(如果有)是相对无害的。当通道本身被垃圾收集时,它将被垃圾收集。当然,这是否合理取决于你用计时器做了什么,但在这些情况下,只需c就足够了所有t.Stop
并忽略其返回值。立即停止计时器并不是偶然的。我更希望创建它,但还没有开始计时,这样它只在另一个通道的事件发生时开始计时,但我不知道如何做。如果我只是将var设置为type*timer而不是启动计时器t当选择被卡住时,我必须启动计时器,然后立即停止。@Debashish:因为频道是同步点,t.C
有一个缓冲区条目,所以可能性有限:要么频道中有一个滴答声,要么没有;要么有人走常规;我喜欢把他们看作人,或者gophers-*在接收中被*阻止,如果不是;当您调用t.Stop
时,发送滴答声的goroutine(系统goroutine)已开始发送,或者尚未开始发送。因此:假设goroutine a在接收中被阻止(虽然B可以尝试对此进行补偿,但最好是以不会卡住的方式编写A:即,它有一个条件接收,并带有一个select
。让我们为Goroutine指定名称,以便于谈论它们。Goroutine A在中,但这种代码通常很棘手。如果A有呢已经等待了5秒,而不是2秒,当B调用t.Reset(10)
?S将在10秒后发送另一个滴答声时,S已经开始并正在发送滴答声。如果不知道a和B的其余代码,我们无法判断会发生什么。
package main
import (
"fmt"
"log"
"time"
)
func main() {
timer := time.NewTimer(time.Second)
watcher := make(chan bool)
done := make(chan bool)
evs := make(chan bool)
go func() {
trigger := false
for {
select {
case <-timer.C:
if trigger {
trigger = false
evs <- true
}
timer.Reset(time.Second)
case _, ok := <-watcher:
if !ok {
return
}
trigger = true
case <-done:
fmt.Println(`DONE TRIGGERED`)
return
}
}
}()
go func() {
for e := range evs {
log.Println("e", e)
}
}()
// simulate multiple events
watcher <- true
watcher <- true
watcher <- true
watcher <- true
<-time.After(time.Second + time.Millisecond*100)
watcher <- true
watcher <- true
watcher <- true
<-time.After(time.Second + time.Millisecond*100)
fmt.Println("Hello, playground")
}
if !t.Stop() {
<-t.C
}
if !t.Stop() {
select {
case <-t.C:
default:
}
}