最近在通讀 《The Go Programming Language》失受,真是好書(shū)。
讀到 gorotuine份帐,想到之前寫 javascript 時(shí)常常需要一個(gè) poller 輪詢一些后臺(tái)任務(wù)的執(zhí)行結(jié)果,其實(shí)用 golang 的 gorutine 和 channel 實(shí)現(xiàn)可以更簡(jiǎn)潔而高效。
看代碼:
// Intervaler 是個(gè)接口用來(lái)讓調(diào)用者自定義poller輪詢時(shí)間間隔
type Intervaler interface {
Interval() time.Duration
}
// IntervalerFunc 用來(lái)將 func() time.Duration 轉(zhuǎn)化成 Intervaler
type IntervalerFunc func() time.Duration
func (intervalerFunc IntervalerFunc) Interval() time.Duration {
return intervalerFunc()
}
type Poller struct {
//要執(zhí)行的方法
do func() error
//用于調(diào)用者傳遞停止信號(hào)
cancle chan int
//下次調(diào)用的時(shí)間間隔
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)
// 或者結(jié)束整個(gè)輪詢
// poller.Cancel()
}
}()
}
}
}
// Cancel 向 cancel 發(fā)送信號(hào)
func (poller *Poller) Cancel() {
println("Polling stopped")
poller.cancle <- 1
}
// NewPoller 創(chuàng)建一個(gè)新的 Poller
func NewPoller(intervaler Intervaler, do func() error) *Poller {
return &Poller{do: do, cancle: make(chan int), nextInterval: intervaler}
}
再來(lái)看看如何使用:
func main() {
// 自定義 Intervaler
base := time.Second * 0
interval := IntervalerFunc(func() time.Duration {
next := base
base += 500 * time.Millisecond
return next
})
// 創(chuàng)建一個(gè) 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)
// 開(kāi)始 polling
poller.Poll()
}
輸出:
ping!
ping!
Polling stopped
差不多就是這么多了碳胳,大家可以根據(jù)不同的業(yè)務(wù)需求靈活自定義 Poller 的細(xì)節(jié)。