dro44817 2016-04-27 10:02
浏览 175
已采纳

使用time在golang中间隔执行重复性任务。

I just want to do repetitive background tasks in Go, using time.AfterFunc,But seems something wrong with the logic. The out put just: interval call interval call

But at least 5 times to call the function if all things went normal.

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)
}

Run Code

  • 写回答

2条回答 默认 最新

  • doushifen4060 2016-04-27 10:45
    关注

    time.AfterFunc() returns a *time.Timer, quoting form its doc:

    The Timer type represents a single event. When the Timer expires, the current time will be sent on C, unless the Timer was created by AfterFunc.

    The time.Timer returned by time.AfterFunc() does not repeat, so what you see is perfectly normal: in your PipeService.IntervalCall() you execute the callback immediately, and it gets executed after the timeout.

    Also note that you pass 2 as interval for the PipeService.IntervalCall() method. This interval parameter is of type time.Duraion. So when you pass 2, that won't be 2 seconds (but actually 2 nanoseconds). You should pass a value constructed from constants from the time package like:

    InsPipeService.IntervalCall(2 * time.Second, func(){
        fmt.Println("interval call")
    })
    

    If you want repetition, use time.Ticker. For example the following code prints a message in every 2 seconds:

    t := time.NewTicker(2 * time.Second)
    for now := range t.C {
        fmt.Println("tick", now)
    }
    

    Or simply if you don't need the Ticker and you don't want to shut it down:

    c := time.Tick(2 * time.Second)
    for now := range c {
            fmt.Println("tick", now)
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 请问在阿里云服务器中怎么利用数据库制作网站
  • ¥60 ESP32怎么烧录自启动程序
  • ¥50 html2canvas超出滚动条不显示
  • ¥15 java业务性能问题求解(sql,业务设计相关)
  • ¥15 52810 尾椎c三个a 写蓝牙地址
  • ¥15 elmos524.33 eeprom的读写问题
  • ¥15 使用Java milo连接Kepserver服务端报错?
  • ¥15 用ADS设计一款的射频功率放大器
  • ¥15 怎么求交点连线的理论解?
  • ¥20 软件开发方法学习来了