SoFunction
Updated on 2025-03-01

golang Detailed explanation of the usage and implementation principle of the timer at one time

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 atTimerIf you need it, please refer to the following content, I hope it will be helpful to you.

Timer

Timeris a single event timer, that is, an event is triggered after a specified time, becauseTimerExecute only once and end, so it is called a single event, which is provided by itselfchannelMake notification triggers.

Timer structure

passsrc/:TimerDefinedTimerData 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 arriveschannelWrite 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	<- 
	("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)
	<- 
	("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 := &amp;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(&amp;) // 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 thenpassstartTimer()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 tosendTime, the execution parameters arechannelsendTimeIt 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) &lt;- 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!