This is a creation in Article, where the information may have evolved or changed.
We will always use a timer to perform some scheduled tasks, and recently in the Go language timer using the above accidentally stepped on a bit of a problem, here to record.
go demo(input)func demo(input chan interface{}) { for { select { case msg <- input: println(msg) case <-time.After(time.Second * 5): println("5s timer") case <-time.After(time.Second * 10): println("10s timer") } }}
The purpose of this program is to continue receiving messages from input channel for processing, and to perform a scheduled task each 5 seconds and every 10 seconds. But when you execute this program, as long as the message in the input channel is fast enough and uninterrupted, you will find that the two scheduled tasks that are started will never be executed, and even if no message arrives, the second 10s timer will never be executed. The reason for this is that select executes the case condition statement again and re-registers it in select, so that the two timed tasks are started with a new timer object starting from the beginning of time, so the two scheduled tasks will never be executed at each execution of a select.
In fact
select {case msg <- input:case <-time.After(time.Second)}
This takes advantage of time. After () The programming of starting the Timer is mainly used to solve the Timeout problem of channel operation, rather than perform a timed task. How does the Go language use this approach to achieve the channel Timeout? This topic is not analyzed here for the time being.
How to use the timer correctly to complete the scheduled tasks mentioned above?
func demo(input chan interface{}) { t1 := time.NewTimer(time.Second * 5) t2 := time.NewTimer(time.Second * 10) for { select { case msg <- input: println(msg) case <-t1.C: println("5s timer") t1.Reset(time.Second * 5) case <-t2.C: println("10s timer") t2.Reset(time.Second * 10) } }}
The corrected procedure, in principle, is to customize the two global timer, and each time the select is executed, the two timer is reused, not every time a new one is generated. In this way, you can actually receive the message at the same time, you can also perform the corresponding tasks on a regular basis.