This is the 27th day of my participation in Gwen Challenge

GO timers Timer and scheduled task Cron

Last time we talked about swaggo in GO, let’s review

  • What is swaggo
  • What is the swagger
  • How to use Swaggo
  • How to test Swaggo

If you’re interested in the swagGo application in GO, check out how the back end provides the API at work. Swaggo is very good

We can do it again laterswaggoThe principle of sharing, thin understandingswaggoHow is it generatedswaggerThe document

Today let’s take a look at GO’s Timer and Timer task cron

Let’s take a look at how timers and timed task crons are used today. We will share more about their principles in a future article

What is a Timer?

GO provides a Timer package, mainly using time.Timer

A timer is actually a single event timer

That is, an event is triggered after a specified time, and this event is notified through the channel provided by the Timer itself. Since the Timer is executed only once, it is called a single event

This is one of the most important differences between the Timer and the Ticker

The general process looks like this:

A separate coroutine is launched when Go runs

This coroutine performs a function of TimerProc to maintain a minimal heap

The coroutine periodically wakes up and reads the timer object at the top of the heap, executing the timer object’s corresponding function (i.e., sending a piece of data in timer.c to trigger the timer).

After execution, the timer object is removed from the minimum heap

When we create a time.Timer, we actually add a Timer object instance to the smallest heap, so we need to Stop the Timer, that is, when we use timer.stop, we remove the corresponding Timer object from the heap

This article will not elaborate on the practical principles, we will briefly apply it first, and share details later

All things are difficult at the beginning, then in the middle, and finally at the end

How is Timer used?

Let’s take a quick look at the data structure of the Timer

Location: SRC /time/sleep.go:Timer

Timer stands for one time, and when the time comes, only one event happens, only one event happens, so this is particularly important

Timer exposes only one channel to the outside world. When the specified time is up, the system time will be written into this channel. When the time is up, an event will be triggered

type Timer struct { 
    C <-chan Time
    r runtimeTimer
}
Copy the code

Let’s use the Timer in the following scenarios

  • The basic use
  • Time delay
  • Stop timer
  • Reset timer

The basic use

Let’s set a timer for 1s that will only trigger once

Create a timer:

func New*Timer*(d Duration) Timer

Specify a time to create a Timer, and the Timer starts as soon as it is created. No additional start command is required

func main(a) {
    // Create a Timer
   myT := time.NewTimer(1 * time.Second)
    // Read data from the channel, if read, the time is up
   <- myT.C
   fmt.Println("One s time is up.")

   for{}}Copy the code

Time delay

Set a timer for 1 second and delay by 2 seconds

func main(a) {
    // Create a Timer
   myT := time.NewTimer(1 * time.Second)
   <- myT.C
   fmt.Println("One s time is up.",time.Now().Unix())
   
   // Delay 2 seconds
   <-time.After(2 * time.Second)
   fmt.Println("Two seconds is up.",time.Now().Unix())
   
   for{}}Copy the code

The execution effect of the running code is as follows:

1 s to 1624757781 2 s to 1624757783Copy the code

GO also provides a function AfterFunc

func AfterFunc(d Duration, f func()) *Timer

We can delay it, and even better, after we delay it, we can execute the function that we’re filling in

Stop timer

After the Timer is created, it can be stopped at any time. We can use time.stop () to Stop the Timer:

func (t *Timer) Stop() bool

The Stop() function returns bool, either true or false, indicating whether the timer times out

  • true

If the timer expires, no more events will be sent

  • false

The timer is stopped after the timeout

Write a DEMO and set the timer for 1 s

If at 1 s, print, indicating timeout

If the channel has not been closed before 1 s, it has not timed out

func testChannelTimeout(conn chan int) bool {
   // Set a timer of 1 second. If the timer reaches 1 second, print it
   timer := time.NewTimer(1 * time.Second)

   select {
   case <-conn:
       if (timer.Stop()){
           fmt.Println("timer.Stop()")}return true
   case <-timer.C: // The timer channel times out
      fmt.Println("timer Channel timeout!")
      return false}}func main(a) {

   ch := make(chan int.1)
    // If the following statement is enabled, the timer can be normally shut down
    // If the following statement is commented, the timer timeout is disabled
   //ch <- 1
   go testChannelTimeout(ch)

   for{}}Copy the code

In the above code, whether to turn off the timer timeout is closely related to another secondary channel

If the following statement is enabled, the timer can be normally disabled

If the following statement is commented, the timer times out

ch <- 1

Reset timer

Start with a fish memory, a 7 second timer

Reset the timer to a one-second timer immediately

func main(a) {
   // Create a memory of the Timer fish
   fmt.Println("Start", time.Now().Unix())
   myT := time.NewTimer(7 * time.Second)
   // Reset the timer to 1s
   myT.Reset(1 * time.Second)
   <-myT.C
   fmt.Println("One s time is up.", time.Now().Unix())

   for{}}Copy the code

After running the above code, the effect is as follows:

Start 1624759572 1 s time to 1624759573Copy the code

The above Timer is triggered once and takes effect once, which cannot meet all scenarios, such as the scenario of periodic execution

We can use the Ticker in GO

What is a Ticker?

A Ticker is also a timer, but it’s a periodic timer,

That is, it is used to trigger an event periodically, passing it out through a pipe provided by the Ticker itself

The Ticker exposes only one channel to the outside world. When the specified time is up, the system time, that is, an event, is written to the channel. Here the time is up, only the periodic time is up

How is Ticker used?

The position is: SRC /time/tick.go:Timer

Type Ticker struct and type Timer struct {are identical

// A Ticker holds a channel that delivers ``ticks'' of a clock
// at intervals.
type Ticker struct {
   C <-chan Time // The channel on which the ticks are delivered.
   r runtimeTimer
}
Copy the code

Creating and closing timers is similar to the above Timer methods, let’s list them together

Create Ticker timer (emphasis: this is a periodic timer)

func NewTicker(d Duration) *Ticker

The Ticker timer is disabled

func (t *Ticker) Stop()

Simple applicationTicker

Set the periodic timer Ticker to 2 seconds

ticker := time.NewTicker(2 * time.Second)
defer ticker.Stop()

// If the channel is empty, it is blocked
// If the channel has data, then read
// Exit if the channel is closed
for range ticker.C {
   fmt.Println("ticker ticker ticker ...")}Copy the code

Let’s do a general version DEMO

Periodic execution of tasks, we can flexibly set the time, and specific tasks to deal with

  • encapsulationTickerThe call
// Define the function type
type Fn func(a) error

// Member of the timer
type MyTicker struct {
	MyTick *time.Ticker
	Runner Fn
}

func NewMyTick(interval int, f Fn) *MyTicker {
	return &MyTicker{
		MyTick: time.NewTicker(time.Duration(interval) * time.Second),
		Runner: f,
	}
}

// Start the task to be executed by the timer
func (t *MyTicker) Start(a) {
	for {
		select {
		case <-t.MyTick.C:
			t.Runner()
		}
	}
}

func testPrint(a){
	fmt.Println("One tick")}func main(a) {
	t := NewMyTick( 1 ,testPrint)
	t.Start()
}
Copy the code

Execute the above code, the operation effect:

Tick 1, tick 1, tick 1...Copy the code

A Timer that fires once, a Ticker that fires periodically, we’ve used it all

What is a cron?

If you’ve ever used Linux, you probably have some ideas about Cron

In Linux, we can use crontab -e to set scheduled tasks. In GO, we can also use cron package to set scheduled tasks

However, in Linux, the above scheduled tasks can only be performed at a higher level than minutes

We can support GO to the second level

How to use Cron?

Package to use: “github.com/robfig/cron”

The basic syntax of Cron is similar to that of Linux. Here are some examples:

// Every 1 second */1 * * * *? // Execute 0 */1 * * * every 1 minute? 0 0 0 * *? 0 0 1 1 *? // Execute 0, 1,2,3 * * *? 0 0 0,1,2 * *?Copy the code

Explain some of the characters above:

Match all values of the field, for example, */1 * * * *? The second * is for every minute

  • /

For example, 0 */1 * * *? Indicates that the command is executed every minute

  • .

Enumerated values

For example, seconds can be any number from 1 to 59 seconds, 1,3,5 * * * *? “, which means 1, 3, 5 seconds per minute

The optional range of hours, minutes, and seconds is 1-59

The range of daily options is 1-31

Monthly options range from 1 to 12

Year options range from 1 to 12

Week ranges from 0 to 6 for Sunday-Saturday

Represents a range, for example, 1-10/2 * * * *? , refers to 1 to 10 minutes per minute, every 2 seconds, perform the task

  • ?

Used to indicate the day or week

Let’s do a simple example

Set the task to be executed every 2 seconds

func main(a) {
   i := 0
   c := cron.New()
   spec := "*/2 * * * *?"
   err := c.AddFunc(spec, func(a) {
      i++
      fmt.Println("cron times : ", i)
   })
   iferr ! =nil {
      fmt.Errorf("AddFunc error : %v",err)
      return 
   }
   c.Start()

   defer c.Stop()
   select{}}Copy the code

Cron is very simple to use. If you are interested in it, you can practice it a lot. We will talk about its principle later

conclusion

  • What is the Timer
  • How to use Timer
  • What is the Ticker
  • How is Ticker used
  • What is the cron
  • How to use Cron

Welcome to like, follow and favorites

Friends, your support and encouragement, I insist on sharing, improve the quality of the power

Ok, that’s all for now. How to play the log of GO next time

Technology is open, our mentality, should be more open. Embrace change, live in the sun, and strive to move forward.

I am Nezha, welcome to like, see you next time ~