如标题,封装一个golang的定时器,能够设置超时时间和定时器的interval。开启定时器后使用一个新的goroutine进行倒计时操作。

好,下面上货。

package commonimport ("context""fmt""github.com/google/uuid""go.uber.org/atomic""time"
)const (STOP    = 0RUNNING = 1
)type ClockCountDown struct {clockId  string //clock标识timeout  int64  //超时秒数interval int64  //间隔秒数ticker   *time.Tickerflag     *atomic.Int32 //是否运行
}//新建一个定时器
func NewClockCountDown(timeout, interval int64) ClockCountDown {tmpTicker := time.NewTicker(time.Duration(interval) * time.Second)return ClockCountDown{clockId:  uuid.New().String(),timeout:  timeout,interval: interval,ticker:   tmpTicker,flag:     atomic.NewInt32(0),}
}/**
开始倒计时*/
func (ccd *ClockCountDown) StartCountDown(intervalFunc func(param interface{}) bool, param1 interface{}, overFunc func(param interface{}), param2 interface{}) {if ccd.flag.CAS(STOP, RUNNING) {fmt.Printf("clockcountdown start:%s\n", ccd.clockId)go ccd.start(intervalFunc, param1, overFunc, param2)} else {fmt.Printf("clockcountdown already start:%s,can not start more than twice\n", ccd.clockId)}
}/**
intervalFunc 每次执行函数
overFunc 超时/结束执行函数,如果返回false,则会停止定时器*/
func (ccd *ClockCountDown) start(intervalFunc func(param interface{}) bool, param1 interface{}, overFunc func(param interface{}), param2 interface{}) {defer ccd.ticker.Stop()rootCtx := context.Background()ctx, cancelFunc := context.WithTimeout(rootCtx, time.Duration(ccd.timeout)*time.Second)for {select {case <-ctx.Done():fmt.Printf("clockCountDown Done:%s!\n", ccd.clockId)cancelFunc()if overFunc != nil {overFunc(param2)}returncase <-ccd.ticker.C:if intervalFunc != nil {if !intervalFunc(param1) {cancelFunc()}}}}
}

 

在main函数中测试一下效果:

package mainimport ("context""etcdclient/src/common""fmt""sync""time"
)func main() {ccd := common.NewClockCountDown(10, 1)ccd.StartCountDown(p, "abcd", q, "bbbbb")ccd.StartCountDown(p, "abcd", q, "bbbbb")stopTheWorld()
}func p(param interface{}) bool {//做一下转换 param抓换成自己需要的类型即可。fmt.Printf("clock_common running Current time: %v,%s\n", time.Now(), param)return true
}func q(param interface{}) {//做一下转换 param抓换成自己需要的类型即可。fmt.Printf("clock_common down Current time: %v,%s\n", time.Now(), param)
}

运行效果:

clockcountdown start:56bc7589-0a94-4216-9cdb-da8f5815f42a
clockcountdown already start:56bc7589-0a94-4216-9cdb-da8f5815f42a,can not start more than twice
clock_common running Current time: 2020-01-07 12:12:05.486255 +0800 CST m=+1.005142040,abcd
clock_common running Current time: 2020-01-07 12:12:06.489267 +0800 CST m=+2.008080035,abcd
clock_common running Current time: 2020-01-07 12:12:07.485208 +0800 CST m=+3.004031462,abcd
clock_common running Current time: 2020-01-07 12:12:08.487824 +0800 CST m=+4.006562295,abcd
clock_common running Current time: 2020-01-07 12:12:09.489621 +0800 CST m=+5.008359055,abcd
clock_common running Current time: 2020-01-07 12:12:10.490092 +0800 CST m=+6.008756465,abcd
clock_common running Current time: 2020-01-07 12:12:11.486778 +0800 CST m=+7.005367140,abcd
clock_common running Current time: 2020-01-07 12:12:12.487973 +0800 CST m=+8.006561740,abcd
clock_common running Current time: 2020-01-07 12:12:13.489144 +0800 CST m=+9.007658675,abcd
clock_common running Current time: 2020-01-07 12:12:14.487543 +0800 CST m=+10.006058417,abcd
clockCountDown Done:56bc7589-0a94-4216-9cdb-da8f5815f42a!
clock_common down Current time: 2020-01-07 12:12:14.487746 +0800 CST m=+10.006260827,bbbbb

需要注意,如果intervalFunc返回false,那么定时器会结束,不再继续执行。这样能够达到通过定时器内部逻辑控制定时器是否继续执行的目的。