SoFunction
Updated on 2025-03-05

Analysis of the usage and implementation principle of golang timer Timer

Understand the usage and implementation principles of golang timer Timer in one article

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 is a periodic timerTicker. 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
}

Supplement: golang timer Ticker

There is a Ticker structure under the time package

// Ticker keeps a channel and passes "tick" to it every once in a while.type Ticker struct {
	C &lt;-chan Time // A channel for periodically transmitting time information.	r runtimeTimer
}
func NewTicker(d Duration) *Ticker{}

NewTicker returns a new Ticker that contains a channel field and will send the time of the channel every time d. It adjusts the time interval or discards the tick information to accommodate slow-responsive recipients. If d<=0 will panic. Close the Ticker to release relevant resources.

func (t *Ticker) Stop()

Stop closes a Ticker. After closing, no more tick information will be sent. Stop does not close the channel to avoid incorrect reads from that channel.

example

package main

import (
	"fmt"
	"time"
)

func main() {
	t := (5 * ) //Create a timer	defer ()
    
	go sync(t)
	select {

	}
}

func sync(t *) {
	for {
		// Read from chan every 5 seconds		&lt;-
		("Execute data backup tasks:", ().Format("2006-01-02 15:04:05"))
	}
}

This is the article about the usage and implementation principle of golang timer Timer. For more related golang timer content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!