SoFunction
Updated on 2025-03-05

Detailed explanation of the usage skills of Timer timer in Go language

There is a Timer timer function in the time package, the main structures and functions are:

type Timer struct {
    C <-chan Time
    r runtimeTimer
}
func After(d Duration) <-chan Time
func AfterFunc(d Duration, f func()) *Timer
func NewTimer(d Duration) *Timer
func (*Timer) Reset(d Duration) bool
func (*Timer) Stop() bool

Three basic usages:

c := ()
(<-c)
t := ()
(<-)
tc := make(chan int)
(, func() { tc <- 1 })
(<-tc)

AfterThe function is actuallyreturn NewTimer(d).C,andNewTimerThe usage is similar, butTimerThere is alsoResetStopIf there are related requirements, it should be usedNewTimer

AfterFuncIt is equivalent tod DurationAfter that, an execution was createdfgoroutine, returnTimerIt does not block itself, nor can it be used like the previous example, but can be usedResetStopetc.

The reason for the above difference is the useNewTimerandAfterFuncWhen generating a timer, the call parameters used internally are not the same.

NewTimer:

func NewTimer(d Duration) *Timer {
    c := make(chan Time, 1)
    t := &Timer{
        C: c,
        r: runtimeTimer{
            when: when(d),
            f:    sendTime,
            arg:  c,
        },
    }
    startTimer(&)
    return t
}
func sendTime(c interface{}, seq uintptr) {
    // Non-blocking send of time on c.
    // Used in NewTimer, it cannot block anyway (buffer).
    // Used in NewTicker, dropping sends on the floor is
    // the desired behavior when the reader gets behind,
    // because the sends are periodic.
    select {
    case c.(chan Time) <- Now():
    default:
    }
}

NewTimerUsed when the timer is finishedsendTimeFunction, non-blocking directionThe current time is passed in, so when the timer is completed, the content can be retrieved from it.

AfterFunc:

func AfterFunc(d Duration, f func()) *Timer {
    t := &Timer{
        r: runtimeTimer{
            when: when(d),
            f:    goFunc,
            arg:  f,
        },
    }
    startTimer(&)
    return t
}
func goFunc(arg interface{}, seq uintptr) {
    go arg.(func())()
}

AfterFuncIt is called when the timer is completedgoFunc,existgoFuncStart an execution parameterfgoroutine, not correctDo anything, so we can't get the content from it.

Note: The following content is mainly based onNewTimerCreatedTimer

TimerKey points to use:

1. In some tasks, we need to repeat the timing multiple times. Do not use loops to create a large number of timers, as it will affect performance. Try to use it as much as possible.ResetandStopReuse the created timer.

two,TimerofStopThe method will not be closed, which may cause unexpected blockages, such as:

func main() {
    timer := ()
    go func() {
        ()
    }()
    <-
}

This will cause the program to block and cannot exit.

aboutTimerofResetandStopTips for using:

// Use Stop with the following non-blocking methodfunc timerStop(t *) {
    if !() {
        select {
        case &lt;-:
        default:
        }
    }
}
// Execute Stop before Resetfunc timerReset(t *, d ) {
    timerStop(t)
    (d)
}

aboutResetWhy did you want it beforeStoptimePackedResetThe documentation says as follows:

For a Timer created with NewTimer, Reset should be invoked only on stopped or expired timers with drained channels.

For Timers created with NewTimer, Reset should be used on timers that have stopped or expired and have emptied the pipeline.

If a program has already received a value from , the timer is known to have expired and the channel drained, so can be used directly. If a program has not yet received a value from , however, the timer must be stopped and—if Stop reports that the timer expired before being stopped—the channel explicitly drained:

If a program has received a value from it, the timer expires and the pipeline has been emptied, Reset can be used directly. But if the program has not received the value from it, and the timer needs to be stopped, and the Stop method reports that the timer has expired before it is stopped, the pipeline needs to be explicitly empty:

if !() {
    <-
}
(d)

This should not be done concurrent to other receives from the Timer's channel.

This operation should not occur simultaneously with the pipeline where other programs receive the timer.

Note that the above content has not been fully expressed yet.

If we need to stop a timer, and the timer'sStopMethod reports asfalsewhen, the status of the timer, andThere are three possibilities for the state of:

  • Stop has been empty before,
  • Stop has expired before, and the timer writes content to the middle, which is full
  • The information has expired before Stop, and the timer writes content to it. The information has been received by other programs and is empty

The programs in the previous document will only run as expected in the second case.

Two other cases, explicit emptied<-It will block when it is.

It is because of the above situation that the previous one evolvedtimerStopfunction.

But at the same time, it should be understood,timerStopHow to deal with functions when they correspond to the above situations:

  • Select goes to the default branch and skips blocking, but it should be considered that the timer is not stopped by the current Stop
  • Select for explicit emptiation, but it should be taken into account that the timer has not been successfully stopped and the content has been discarded
  • Select goes to the default branch and skips the blocking, but it should be considered that the timer has not been successfully stopped and the content is used by other programs.

Taking into account the above points can be usedtimerStopFunction is here.

Otherwise, you should fully consider the needs of your own program and make necessary modifications.

This is the end of this article about the detailed explanation of the use skills of Timer timer in Go. For more related content of Go Timer timer, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!