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)
After
The function is actuallyreturn NewTimer(d).C
,andNewTimer
The usage is similar, butTimer
There is alsoReset
、Stop
If there are related requirements, it should be usedNewTimer
。
AfterFunc
It is equivalent tod Duration
After that, an execution was createdf
goroutine, returnTimer
It does not block itself, nor can it be used like the previous example, but can be used
Reset
、Stop
etc.
The reason for the above difference is the useNewTimer
andAfterFunc
When 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: } }
NewTimer
Used when the timer is finishedsendTime
Function, 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())() }
AfterFunc
It is called when the timer is completedgoFunc
,existgoFunc
Start an execution parameterf
goroutine, not correctDo anything, so we can't get the content from it.
Note: The following content is mainly based onNewTimer
CreatedTimer
Timer
Key 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.Reset
andStop
Reuse the created timer.
two,Timer
ofStop
The 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.
aboutTimer
ofReset
andStop
Tips for using:
// Use Stop with the following non-blocking methodfunc timerStop(t *) { if !() { select { case <-: default: } } } // Execute Stop before Resetfunc timerReset(t *, d ) { timerStop(t) (d) }
aboutReset
Why did you want it beforeStop
,time
PackedReset
The 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'sStop
Method reports asfalse
when, 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 evolvedtimerStop
function.
But at the same time, it should be understood,timerStop
How 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 usedtimerStop
Function 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!