写在前面
今天看cron源码的时候发现它支持Regist函数和接口,有一点思考。
上代码
// 定义了任务接口
type Job interface {
Run()
}
// 定义了任务函数
type FuncJob func()
func (f FuncJob) Run() { f() }
它支持两种Regist方式
func (c *Cron) AddFunc(spec string, cmd func()) (EntryID, error) {
return c.AddJob(spec, FuncJob(cmd))
}
func (c *Cron) AddJob(spec string, cmd Job) (EntryID, error) {
schedule, err := c.parser.Parse(spec)
if err != nil {
return 0, err
}
return c.Schedule(schedule, cmd), nil
}
其中AddFunc是将cmd转换成了FuncJob类型,因为FuncJob也是一个func,并且函数签名是一样的,这样转没有问题。可是转换之后为什么能调用c.AddJob呢?AddJob的入参是Job接口类型。
关键在于下面这个函数
func (f FuncJob) Run() { f() }
在FuncJob上实现了Job interface,所以能这样转换。
一般很少在函数上定义函数,但是go是支持这样做的。这里这样做,将AddFunc和AddJob两个方法在底层实现了统一,可以学习一下。
源码位置:https://github.com/robfig/cron/blob/master/cron.go#L134