1
头图

GO timer Timer and timing task cron

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

  • What is swaggo
  • What is swagger
  • How to use swapgo
  • How to test swapgo

If you are still interested in the application of swaggo in GO, you can check the article How does the backend provide the API during work? swaggo is very good

Then we can come to a swaggo principle of sharing, thin look swaggo how is generated swagger document

Today, let’s take a look at the timer in GO and the timing task cron

Let’s take a look at how the timer and cron are used today. We will share in detail in the follow-up articles about their principles.

What is Timer?

It is a timer package provided in GO, mainly with time.Timer

timer is actually a single event timer

That is to say, an event is triggered after a specified time. This event channel provided by itself. Because the Timer is executed only once and ends, it is called a single event

Timer and Ticker of most important difference one is here

looks like this: 16125c052562cd

A separate coroutine will be started when Go is running

The coroutine executed a timerproc and maintained a minimum heap

The coroutine will be periodically woken up and read the timer object at the top of the heap, and execute the function corresponding to the timer object (that is, send a piece of data timer.C

After execution, the timer object will be removed from the minimum heap

time.Timer we created is actually adding a timer minimum heap , then we need to stop the timer, that is timer.Stop , we delete the corresponding timer object from this heap

This article does not explain the actual principle in detail, we will briefly apply it first, and we will share it in detail later

Everything is hard at the beginning, then hard in the middle, and hard at the end

How to use Timer?

Let's take a brief look at the data structure corresponding to Timer

The location is: src/time/sleep.go:Timer

Timer represents a timing, only one event occurs after the time comes
It happens only once, here particularly important

Timer only exposes one channel to the outside. When the specified time is up, the system time will be written to the channel. When the time is up, the event will be triggered once, and it will only be triggered once, because the time will only reach once

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

from the following scenarios respectively

  • Basic use
  • Time delay use
  • Stop timer
  • Reset timer

Basic use

Let's set a timer in 1s, this timer will only trigger once

Create a timer:

func New*Timer*(d Duration) Timer

Specify a time to create a Timer , Timer will start timing once it is created, no additional start command is required

func main() {
    // 创建一个 Timer
   myT := time.NewTimer(1 * time.Second)
    // 从通道中读取数据,若读取得到,说明时间到了
   <- myT.C
   fmt.Println(" 1 s 时间到")

   for {}
}

Time delay use

Set a timer of 1 second, and then delay for 2 seconds

func main() {
    // 创建一个 Timer
   myT := time.NewTimer(1 * time.Second)
   <- myT.C
   fmt.Println(" 1 s 时间到 ",time.Now().Unix())
   
   // 延时 2 秒
   <-time.After(2 * time.Second)
   fmt.Println(" 2 s 时间到 ",time.Now().Unix())
   
   for {}
}

The execution effect of running code is as follows:

 1 s 时间到  1624757781
 2 s 时间到  1624757783

GO also provides a function AfterFunc

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

It is also possible to achieve the effect of delay. Better yet, after the delay, the function we filled in can be executed

Stop timer

Timer can be stopped at any time after creation, we can use time.Stop() to stop the timer:

func (t *Timer) Stop() bool

Stop() function return value is bool , either true or false , which means whether the timer expires

  • true

Stop before the timer expires, and no more events will be sent in the future

  • false

The timer is stopped after timeout

Write a DEMO, set the timer of 1 s

If it is 1 s, then print, indicating that it has timed out

If it does not reach 1 s, the channel has been closed, and it has not timed out

func testChannelTimeout(conn chan int) bool {
   // 设置 1 秒的定时器,若在到了1 s ,则进行打印,说明已经超时
   timer := time.NewTimer(1 * time.Second)

   select {
   case <-conn:
       if (timer.Stop()){
           fmt.Println("timer.Stop()")
       }
      return true
   case <-timer.C: // timer 通道超时
      fmt.Println("timer Channel timeout!")
      return false
   }
}

func main() {

   ch := make(chan int, 1)
    // 若打开如下语句,则可以正常关闭定时器
    // 若注释如下语句,则关闭定时器超时
   //ch <- 1
   go testChannelTimeout(ch)

   for {}
}

In the above code, whether the shutdown timer expires is closely related to another auxiliary channel

If you open the following statement, you can turn off the timer normally

If you comment the following statement, turn off the timer timeout

ch <- 1

Reset timer

Set a fish’s memory at the start, a 7-second timer

Immediately reset the timer to a 1-second timer

func main() {
   // 创建一个 Timer 鱼的记忆
   fmt.Println(" 开始 ", time.Now().Unix())
   myT := time.NewTimer(7 * time.Second)
   // 重置定时器为 1 s
   myT.Reset(1 * time.Second)
   <-myT.C
   fmt.Println(" 1 s 时间到 ", time.Now().Unix())

   for {}
}

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

 开始  1624759572
 1 s 时间到  1624759573

The above Timer is triggered once and takes effect once, which cannot satisfy all scenarios. For example, the scenario that is executed periodically is not satisfied.

We can use Ticker

What is Ticker?

Ticker is also a timer, but it is a periodic timer,

In other words, it is used to trigger an event periodically, and pass the event out Ticker

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

How is Ticker used?

The location is: src/time/tick.go:Timer

type Ticker struct and type Timer struct { exactly the same

// 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
}

About creating timers and closing timers are similar to the above Timer methods, let’s enumerate them together

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

func NewTicker(d Duration) *Ticker

Disable Ticker timer

func (t *Ticker) Stop()

Simple application Ticker

Set a 2-second periodic timer Ticker

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

// 若通道为空,则阻塞
// 若通道有数据,则读取
// 若通道关闭,则退出
for range ticker.C {
   fmt.Println("ticker ticker ticker ...")
}

Come to a general version of the DEMO

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

  • Encapsulate the call of Ticker
// 定义函数类型
type Fn func() error

// 定时器中的成员
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,
    }
}

// 启动定时器需要执行的任务
func (t *MyTicker) Start() {
    for {
        select {
        case <-t.MyTick.C:
            t.Runner()
        }
    }
}

func testPrint(){
    fmt.Println(" 滴答 1 次")
}

func main() {
    t := NewMyTick( 1 ,testPrint)
    t.Start()
}

Execute the above code and run the effect:

滴答 1 次
滴答 1 次
滴答 1 次
...

Trigger once Timer , periodic triggered Ticker , we have applied to the

What is cron?

You should be familiar with cron who have used Linux should still have some ideas cron

In linux we can use crontab -e to set timed tasks, in GO, we can also use cron package to set timed tasks

However, the above-mentioned timing tasks in linux

Our GO can support to the second level

How is cron used?

Package used: "github.com/robfig/cron"

About cron basic grammar and in linux when playing a similar, let's briefly enumerate them:

// 每隔1秒执行一次
*/1 * * * * ?

// 每隔1分钟执行一次
0 */1 * * * ?

// 每天0点执行一次
0 0 0 * * ?

// 每月1号凌晨1点执行一次
0 0 1 1 * ?

// 在1分、2分、3分执行一次
0 1,2,3 * * * ?

// 每天的0点、1点、2点执行一次
0 0 0,1,2 * * ?

Explain some of the above characters:

  • *

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

  • /

Represents the growth interval, such as 0 */1 * * * ? , which is executed every minute

Enumerated value

For example, in seconds, you can write any number from 1 to 59 seconds, 1,3,5 * * * * ? , which means that the task will be executed in 1, 3, and 5 seconds every minute

The optional range of hour, minute, and second is 1-59

The daily range is 1-31

Month can be selected from 1-12

Years can be selected from 1-12

The week range is 0-6, which means Sunday-Saturday

  • -

Represents a range, such as 1-10/2 * * * * ? , refers to 1-10 per minute, and executes the task every 2 seconds

  • ?

It is used to represent day or week

is a simple example

Set to execute the task every 2 seconds

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

   defer c.Stop()
   select {}
}

cron is still very simple to use. If you are interested, you can practice more. Regarding their principles, let's follow up.

Summarize

  • What is Timer
  • How to use Timer
  • What is Ticker
  • How to use Ticker
  • What is cron
  • How to use cron

Welcome to like, follow, favorite

Friends, your support and encouragement are my motivation to keep sharing and improve quality

Okay, that’s it for this time. How to play the next GO log

Technology is open, and our mindset should be more open. Embrace the change, live toward the sun, and work hard to move forward.

I am , the little magic boy, welcome to like and follow the collection, see you next time~


阿兵云原生
192 声望37 粉丝