Preface
Timers are widely used in Go language applications. The Go language standard library provides two types of timers, one is a one-time timer.Timer
, the other one isPeriodic timingDeviceTicker
. This article mainly looks atTimer
If you need it, please refer to the following content, I hope it will be helpful to you.
Timer
Timer
is a single event timer, that is, an event is triggered after a specified time, becauseTimer
Execute only once and end, so it is called a single event, which is provided by itselfchannel
Make notification triggers.
Timer structure
passsrc/:Timer
DefinedTimer
Data structure:
// Timer represents a timer, and only one event is executed after the time has arrived.type Timer struct { C <-chan Time r runtimeTimer }
It provides achannel
, no data is written before the timing time arrivesWill be blocked until time arrives
channel
Write to the system time, blocking is released, and data can be read from it, which is an event.
Create a timer
func NewTimer(d Duration) *Timer
By specifying an event, you can create a Timer. Once the Timer is created, it starts to time, and no additional start command is required.
Example:
func main() { timer := ( * 5) //Set the timeout time of 5s &lt;- ("Time out!") }
Stop the timer
After the Timer is created, it can be stopped at any time. The method to stop the timer is as follows:
func (t *Timer) Stop() bool
Its return value indicates whether the timer has timed out:
- true: The timer stops before timeout, and no subsequent events will be sent.
- false: Stop after the timer timed out.
Example:
func main() { timer := ( * 5) //Set the timeout time of 5s () }
Reset timer
An expired timer or a stopped timer can be reactivated by resetting the method as follows:
func (t *Timer) Reset(d Duration) bool
The reset action essentially stops the timer first and then starts, and its return value is the return value of the timer.
func main() { timer := ( * 5) &lt;- ("Time out!") () (*3) // Reset the timer}
Implementation principle
Each Go application has a coroutine that is specifically responsible for managing all Timers. This coroutine is responsible for monitoring whether the Timer expires. After it expires, it executes a predefined action. For Timer, this action is to send the current time to the pipeline.
Data structure
type Timer struct { C <-chan Time r runtimeTimer }
Timer has only two members:
- C:channel, the upper layer application receives events according to this pipeline;
- r:runtimeTimer timer, which is the timer managed by the system and is not visible to the upper layer application.
runtimeTimer
The carrier of the task is used to monitor the timing task. Every time a Timer is created, a runtimeTimer variable is created and then handed over to the system for monitoring. We achieve the purpose of timing by setting the behavior after the runtimeTimer expires.
The source code package src/time/:runtimeTimer defines its data structure:
type runtimeTimer struct { tb uintptr //Storing the array address of the current timer i int // Storing the array subscript of the current timer when int64 // The current timer trigger time period int64 // The current timer cycle trigger interval f func(interface{}, uintptr) // Functions executed when the timer is triggered arg interface{} // When the timer is triggered, the parameter passed by the function is executed seq uintptr // Parameter 2 of the function is passed when the timer is triggered (this parameter is only used in network sending and receiving scenarios)}
Create Timer
Source code implementation:
func NewTimer(d Duration) *Timer { c := make(chan Time, 1) // Create a pipeline t := &Timer{ // Construct Timer data structure C: c, // Newly created pipeline r: runtimeTimer{ when: when(d), // Trigger time f: sendTime, // Execute the function sendTime after triggering arg: c, // The parameters included when executing the function sendTime after triggering }, } startTimer(&) // Start the timer here, just put the runtimeTimer into the heap of the system coroutine and maintain it by the system coroutine return t }
-
NewTimer()
Just constructed oneTimer
, and thenpass
startTimer()
Leave it to the system coroutine maintenance. - C is a chan with 1 capacity. What are the benefits of doing this? The reason is that chan will block without buffering and block system coroutines, which is obviously not possible.
- The callback function is set to
sendTime
, the execution parameters arechannel
,sendTime
It is the function that sends the current time to C at the point
sendTime implementation:
//c interface{} is the parameter assigned by NewTimer, which is the channelfunc sendTime(c interface{}, seq uintptr) { select { case c.(chan Time) <- Now(): //If you can't write it in, C is full, go to the default branch default: } }
Stop Timer
Stop the Timer is to remove the Timer from the system coroutine. The main implementation of the function is as follows:
func (t *Timer) Stop() bool { return stopTimer(&) }
stopTimer() notifies the system coroutine to remove the Timer, that is, it will no longer monitor. System coroutines simply remove Timer and do not close the pipeline to avoid user coroutine read errors.
Reset Timer
When resetting Timer, the timer will be deleted from the system coroutine first, and then modified the new time and added to the system coroutine again.
func (t *Timer) Reset(d Duration) bool { w := when(d) active := stopTimer(&) = w startTimer(&) return active }
The above is the detailed explanation of the usage and implementation principles of golang's one-time timer Timer. For more information about golang's one-time timer Timer, please pay attention to my other related articles!