Example implementation of Golang Cron timed task
- 2020-10-31 21:46:51
- OfStack
Let me get straight to 1
package main
import (
"fmt"
"github.com/robfig/cron"
"log"
"strings"
"time"
)
func CronTask() {
log.Println("******** ******* *******")
}
func CronTest() {
log.Println("Starting Cron...")
c := cron.New()
c.AddFunc("* * * * * *", CronTask) //2 * * * * *, 2 The end of the minute 2s perform 1 time
c.Start()
t1 := time.NewTimer(time.Second * 10) // ?time.Second * 10 What you mean? *100 All right?
for {
select {
case <-t1.C:
fmt.Println("Time now:", time.Now().Format("2006-01-02 15:04:05")) // Why set a specific time
t1.Reset(time.Second * 10)
}
}
}
func main() {
fmt.Println(strings.Repeat("START ", 15))
CronTest()
fmt.Println(strings.Repeat("END ", 15))
}
The core timer code is just 3 lines long
c := cron.New()
c.AddFunc("* * * * * *", CronTask)
c.Start()
What does that last code do?
1 When I first saw the sample code, I had a puzzle, such as comments in the code
t1 := time.NewTimer(time.Second * 10)
Here time.Second*10 what is it? Could I write *100? I changed it so I could, but I'm even more confused if I didn't have to do it why would I have to do it?
And then there's for-ES18en-ES19en, which is also a 1 in a mud-headed state
Run the code, derive the principle from the result, execute the result once
[
START START START START START START START START START START START START START START START
2020/05/01 07:38:07 Starting Cron...
2020/05/01 07:38:08 ******** ******* *******
2020/05/01 07:38:09 ******** ******* *******
2020/05/01 07:38:10 ******** ******* *******
2020/05/01 07:38:11 ******** ******* *******
2020/05/01 07:38:12 ******** ******* *******
2020/05/01 07:38:13 ******** ******* *******
2020/05/01 07:38:14 ******** ******* *******
2020/05/01 07:38:15 ******** ******* *******
2020/05/01 07:38:16 ******** ******* *******
2020/05/01 07:38:17 ******** ******* *******
Time now: 2020-05-01 07:38:17
2020/05/01 07:38:18 ******** ******* *******
2020/05/01 07:38:19 ******** ******* *******
2020/05/01 07:38:20 ******** ******* *******
2020/05/01 07:38:21 ******** ******* *******
2020/05/01 07:38:22 ******** ******* *******
2020/05/01 07:38:23 ******** ******* *******
2020/05/01 07:38:24 ******** ******* *******
2020/05/01 07:38:25 ******** ******* *******
2020/05/01 07:38:26 ******** ******* *******
2020/05/01 07:38:27 ******** ******* *******
Time now: 2020-05-01 07:38:27
2020/05/01 07:38:28 ******** ******* *******
These are the running snippets, and there are two big findings
There are START START START... No END END END... : indicates that the code is blocked in the timer while executing. The timer has not finished executing and will never execute END The spacing is exactly 10sOh, so time.NewTimer is a timer, and when that interval is over, it reopens one. The purpose of the block for-ES93en-ES94en is to block the process and not allow the program to end. Understand right?
If so, remove ES97en-ES98en-ES99en you can also stop 10s when you run the first timer, right? Under test: block for-ES102en-ES103en, output
[
START START START START START START START START START START START START START START START
2020/05/01 07:56:22 Starting Cron...
END END END END END END END END END END END END END END END
It seems that blocking is mainly achieved by for-ES117en-ES118en. What is the principle?
Remove t1. How does Reset work?
t1 := time.NewTimer(time.Second * 10) // ?time.Second * 10 What you mean? *100 All right?
for {
fmt.Println("hihihihi")
select {
case <-t1.C:
fmt.Println("hello")
}
}
The output
[
START START START START START START START START START START START START START START START
2020/05/01 08:12:21 Starting Cron...
hihihihi
2020/05/01 08:12:22 ******** ******* *******
2020/05/01 08:12:23 ******** ******* *******
2020/05/01 08:12:24 ******** ******* *******
2020/05/01 08:12:25 ******** ******* *******
2020/05/01 08:12:26 ******** ******* *******
2020/05/01 08:12:27 ******** ******* *******
2020/05/01 08:12:28 ******** ******* *******
2020/05/01 08:12:29 ******** ******* *******
2020/05/01 08:12:30 ******** ******* *******
2020/05/01 08:12:31 ******** ******* *******
hello
hihihihi
2020/05/01 08:12:32 ******** ******* *******
2020/05/01 08:12:33 ******** ******* *******
2020/05/01 08:12:34 ******** ******* *******
2020/05/01 08:12:35 ******** ******* *******
2020/05/01 08:12:36 ******** ******* *******
To make matters worse, reset was removed and the first timer 10s was run. Instead of listening, it was executed without stopping
The print in the for cycle is not a big chunk of the case, but a hit of the case, so it's time to understand how select-ES180en works
select case
And the convention is to do the last example
package main
import (
"fmt"
"strings"
)
func SelectTest() {
intChan := make(chan int, 1)
stringChan := make(chan string, 1)
intChan <- 123456
stringChan <- "hello"
select {
case value := <-intChan:
fmt.Println(value)
case value := <- stringChan:
fmt.Println(value)
}
}
func main() {
fmt.Println(strings.Repeat("START ", 15))
SelectTest()
fmt.Println(strings.Repeat("END ", 15))
}
After many executions, you can see that the output is 123456, "hello" is variable
select grammar
Each case must be a communication
If 1 communication can be made it is executed and the others are ignored
If there are multiple case executables, one will be selected at random
If there is no case, if there is default, execute the default statement; Otherwise, it will block until some communication is feasible
There are still a lot of problems here. Make sure you understand the select statement in section 1
Go back to the timer task from 1
Review topic, timing principle analysis
t1 := time.NewTimer(time.Second * 10)
for {
select {
case <-t1.C:
fmt.Println("Time now:", time.Now().Format("2006-01-02 15:04:05"))
t1.Reset(time.Second * 10)
}
}
1 timer t1 is generated and for loop is executed. Before the start time of 1 (10s) arrives and the task is not blocked, it will block in case.
When the timing time is up, execute the statement in case;
And then it goes back to the timing
Go back to the for loop and repeat the above story
In the above code, an attempt to remove ES226en1.Reset from case resulted in a different execution of the timed task. The reason was that after the statement in case was executed, the for loop was executed. Since there was no new communication (the case statement could never be satisfied), and there was no default statement, it could block again.
Compared with case t1 Reset, t1 Reset is more flexible, because it can do one more flexible operation each time it satisfies case, such as jumping out of the loop, doing one more statistical printing, etc.