Why

Periodic operations are required in application development, for example, analyzing the logs of the previous day at dawn every day, checking certain services every five minutes, and triggering alarms. These functions need to be implemented using a timed task approach, so how do we use Golang to achieve this?

What

The Golang open source library on Github is recommended for implementing scheduled tasks. Two common libraries are robfig/ Cron and JasonLvhit/Gocron

  • robfig/cron: When it comes to scheduled tasks, it comes to mindcrontab, which is common in Unix and UniX-like operating systems. The Robfig/Cron library uses a crontab-like approach to perform scheduled tasks.
  • Jasonlvhit/Gocron: While the crontab-like setup may not be friendly, jasonLvhit/Gocron provides a more user-friendly implementation.

Which one to choose? If you are familiar with Crontab, you can choose Cron. If you want more readability, you can choose Gocron. Both of them have good functions and stability.

Ouqiang/Gocron Star & Fork Sigma (o゚ ゚o Blue) if you need a timed task management system out of the box

This is the version the department will use internally, and that will be convenient. ◕ ‿ ‿ ◕.) The README you guys understand is clear, and I won’t cover it here

How

Below, a brief introduction to robfig/ Cron and Jasonlvhit/Gocron usage

cron

Install go get -u github.com/robfig/cron

Demo

package main

import (
	"log"

	"github.com/robfig/cron"
)

func main(a) {
	i := 0
	c := cron.New()
	spec := "*/5 * * * *"
	c.AddFunc(spec, func(a) {
		i++
		log.Println("execute per 5 seconds", i)
	})
	c.Start()
	select{}}Copy the code

The result is as follows (code description: every 5 seconds, I is accumulated and recorded to print) :

Golang’s select function is similar to that of select, poll, and epoll. Golang’s select function is similar to that of select, poll, and epoll. Golang’s select function is similar to that of select, poll, and epoll.

Similarly, if you want to run the spec := “0 */1 * * * *” command, you can change the spec := “0 */1 * * * *” command. The summary is as follows:

The field name Whether must Allowed values A specific character that is allowed
Seconds (Seconds) is 0-59 * /, –
(Minutes) is 0-59 * /, –
(Hours) is 0-23 * /, –
Day (Day of the month) is 1-31 * /, –?
Month (Month) is 1-12 or JAN-DEC * /, –
Day of Week is 0-6 or SUM-SAT * /, –?

Remark:

  1. The values of the month and week segments are case insensitive, for example: SUN, SUN, and SUN are the same.
  2. The previous version of the Day of Week field appears to be optional.

Special Characters

  1. Asterisk (*) : indicates that the CRon expression matches all the values of the field.
  2. Slash (/) : indicates growth interval; Such as:spec := "*/5 * * * * *" 
  3. Comma (,) : used to enumerate values. For example, the sixth field value is MON,WED,FRI, indicating Monday, Wednesday, and Friday. Another example:Spec := "* 0,59, 1"Is executed every second at 01:00 and 01:59 minutes every day
  4. Hyphen (-) : indicates a range, such as the value of the third field 9-17 indicates 9am to 5pm directly per hour (including 9 and 17)
  5. Question mark : Applies only to Day of month and week, indicating that no value is specified and can be used instead of *

You can also use some preset timers to facilitate execution, as follows:

Entry Description Equivalent To
@yearly (or @annually) Execute Run once a year, midnight, Jan. 1st every year 0, 0, 1, 1 star
@monthly Execute Run once a month, midnight, first of month every month 0, 0, 0, 1 * *
@weekly Run once a week, midnight between Sat/Sun 0, 0, 0 * * 0
@daily (or @midnight) Execute Run once a day, midnight every day 0, 0, 0 * * *
@hourly Run once an hour, beginning of hour 0 0 * * * *

More references: godoc.org/github.com/…

gocron

Install the go get -u github.com/jasonlvhit/gocron

Demo

package main

import (
	"log"

	"github.com/jasonlvhit/gocron"
)

func main(a) {
	i := 0
	s := gocron.NewScheduler()
	s.Every(5).Seconds().Do(func(a) {
		i++
		log.Println("execute per 5 seconds", i)
	})
	<-s.Start()
}

Copy the code

The execution effect is as follows:

The above is the basic timer usage mode. The naming and use of gocron interface are relatively user-friendly and can be read directly. Please refer to the following official examples:

package main

import (
	"fmt"
	"github.com/jasonlvhit/gocron"
)

func task(a) {
	fmt.Println("I am runnning task.")}func taskWithParams(a int, b string) {
	fmt.Println(a, b)
}

func main(a) {
	// Do jobs with params
	gocron.Every(1).Second().Do(taskWithParams, 1."hello")
	
	// Do jobs safely, preventing an unexpected panic from bubbling up
	gocron.Every(1).Second().DoSafely(taskWithParams, 1."hello")

	// Do jobs without params
	gocron.Every(1).Second().Do(task)
	gocron.Every(2).Seconds().Do(task)
	gocron.Every(1).Minute().Do(task)
	gocron.Every(2).Minutes().Do(task)
	gocron.Every(1).Hour().Do(task)
	gocron.Every(2).Hours().Do(task)
	gocron.Every(1).Day().Do(task)
	gocron.Every(2).Days().Do(task)

	// Do jobs on specific weekday
	gocron.Every(1).Monday().Do(task)
	gocron.Every(1).Thursday().Do(task)

	// function At() take a string like 'hour:min'
	gocron.Every(1).Day().At("At 10:30").Do(task)
	gocron.Every(1).Monday().At("Him").Do(task)

	// remove, clear and next_run
	_, time := gocron.NextRun()
	fmt.Println(time)

	gocron.Remove(task)
	gocron.Clear()

	// function Start start all the pending jobs
	<- gocron.Start()

	// also, you can create a new scheduler
	// to run two schedulers concurrently
	s := gocron.NewScheduler()
	s.Every(3).Seconds().Do(task)
	<- s.Start()
}
Copy the code

More references: godoc.org/github.com/…