我只想在Go中执行重复的后台任务,使用time.AfterFunc,但逻辑似乎有问题。 出局只是: 间隔呼叫 间隔呼叫
但如果一切正常,至少要调用5次。
package main
import (
"fmt"
"time"
"os"
"os/signal"
)
type Timer struct {
Queue chan *TimeCall
}
func NewTimer(l int) *Timer {
timer := new(Timer)
timer.Queue = make(chan *TimeCall,l)
return timer
}
type TimeCall struct {
timer *time.Timer
callback func()
}
func (this *TimeCall) CallBack() {
defer func() { recover() }()
if this.callback != nil {
this.callback()
}
}
func (this *Timer) AfterFunc(d time.Duration, callback func()) *TimeCall {
call := new(TimeCall)
call.callback = callback
call.timer = time.AfterFunc(d, func() {
this.Queue <- call
})
return call
}
type PipeService struct {
TimeCall *Timer
}
func (this *PipeService) AfterFunc(delay time.Duration, callback func()) *TimeCall {
return this.TimeCall.AfterFunc(delay, callback)
}
func (this *PipeService) IntervalCall(interval time.Duration, callback func()) {
this.TimeCall.AfterFunc(interval,func(){
if callback != nil {
callback()
}
this.AfterFunc(interval,callback)
})
}
func (this *PipeService) Run(closeSig chan bool) {
for {
select {
case <-closeSig:
return
case call := <-this.TimeCall.Queue:
call.CallBack()
}
}
}
func main() {
var closeChan chan bool
InsPipeService := &PipeService{TimeCall: NewTimer(10)}
InsPipeService.IntervalCall(2*time.Second,func(){
fmt.Println("interval call")
})
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, os.Kill)
go func(){
InsPipeService.Run(closeChan)
}()
time.Sleep(10*time.Second)
}
答案 0 :(得分:2)
time.AfterFunc()
返回*time.Timer
,引用其文档:
计时器类型代表单一事件。当Timer到期时,当前时间将在C上发送,除非Timer由AfterFunc创建。
time.Timer
返回的time.AfterFunc()
不重复,所以你看到的是完全正常的:在PipeService.IntervalCall()
中你立即执行回调,并在超时后执行。< / p>
另请注意,您将2
作为PipeService.IntervalCall()
方法的间隔传递。此interval
参数的类型为time.Duraion
。所以当你通过2
时,那不会是2秒(但实际上是2纳秒)。您应该传递一个由time
包中的常量构造的值,如:
InsPipeService.IntervalCall(2 * time.Second, func(){
fmt.Println("interval call")
})
如果您想重复,请使用time.Ticker
。例如,以下代码每2秒打印一条消息:
t := time.NewTicker(2 * time.Second)
for now := range t.C {
fmt.Println("tick", now)
}
或者只是如果您不需要Ticker
并且您不想将其关闭:
c := time.Tick(2 * time.Second)
for now := range c {
fmt.Println("tick", now)
}
答案 1 :(得分:0)
设置时间间隔然后调用Start它将在每个时间间隔运行用户Job。将Enabled设置为false以停止它 我的样本:
package main
import (
"fmt"
"sync"
"time"
)
type IntervalTimer struct {
Interval time.Duration
Enabled bool
Job func()
Wg sync.WaitGroup
}
func (it *IntervalTimer) isr() {
if it.Enabled {
it.Job()
time.AfterFunc(it.Interval, it.isr)
} else {
it.Wg.Done()
}
}
//trigger
func (it *IntervalTimer) Start() {
if it.Enabled {
it.Wg.Add(1)
time.AfterFunc(it.Interval, it.isr)
}
}
// user code:
var n int = 5
var it *IntervalTimer
func uerTask() {
fmt.Println(n, time.Now()) // do user job ...
n--
if n == 0 {
it.Enabled = false
}
}
func main() {
it = &IntervalTimer{Interval: 500 * time.Millisecond, Enabled: true, Job: uerTask}
it.Start()
//do some job ...
it.Wg.Wait()
fmt.Println("Bye")
}