golang poller

最近在通读 《The Go Programming Language》,真是好书。

读到 gorotuine,想到之前写 javascript 时常常需要一个 poller 轮询一些后台任务的执行结果,其实用 golang 的 gorutine 和 channel 实现可以更简洁而高效。

看代码:

// Intervaler 是个接口用来让调用者自定义poller轮询时间间隔
type Intervaler interface {
    Interval() time.Duration
}

// IntervalerFunc 用来将 func() time.Duration 转化成 Intervaler
type IntervalerFunc func() time.Duration

func (intervalerFunc IntervalerFunc) Interval() time.Duration {
    return intervalerFunc()
}

type Poller struct {
    //要执行的方法
    do           func() error
    //用于调用者传递停止信号
    cancle       chan int
    //下次调用的时间间隔
    nextInterval Intervaler
}

// Poll 轮询
func (poller *Poller) Poll() {
    for {
        select {
        case <-poller.cancle:
            return
        case <-time.After(poller.nextInterval.Interval()):
            go func() {
                if err := poller.do(); err != nil {
                    log.Errorf("Poll poller.go: polling method returns a error: %v", err)
                    // 或者结束整个轮询
                    // poller.Cancel()
                }
            }()
        }
    }
}

// Cancel 向 cancel 发送信号
func (poller *Poller) Cancel() {
    println("Polling stopped")
    poller.cancle <- 1
}

// NewPoller 创建一个新的 Poller
func NewPoller(intervaler Intervaler, do func() error) *Poller {
    return &Poller{do: do, cancle: make(chan int), nextInterval: intervaler}
}

再来看看如何使用:

func main() {
    // 自定义 Intervaler
    base := time.Second * 0
    interval := IntervalerFunc(func() time.Duration { 
      next := base
      base += 500 * time.Millisecond
      return next 
    })

    // 创建一个 poller
    poller := NewPoller(interval,
        func() error {
            // 4秒后 输出 ping!
            time.AfterFunc(time.Second*4, func() { println("ping!") })
            return nil
        })
    // 5 秒后停止 polling
    time.AfterFunc(time.Second*5, poller.Cancel)
    // 开始 polling
    poller.Poll()
}

输出:

ping!
ping!
Polling stopped

差不多就是这么多了,大家可以根据不同的业务需求灵活自定义 Poller 的细节。

你可能感兴趣的:(golang poller)