Time is everything in our daily lives but even more so when it comes to programming such as scheduling tasks, implementing timeouts, building concurrent applications, and more.
In Go, we have timers which allows us to efficiently create work with times. Timers are provided by the “time” package.
In this tutorial, we will teach you everything you need to know about timers in Go. We will learn things like what timers are, the common uses of timers, and then the detailed implementations of timers.
Golang Timers
Timers are time-based events that triggers a specific action at a predefined point in the future. Think of it as way of setting up a future event.
Timers play a fundamental role for handling the time-related operations in Go applications.
Timers are useful for various purposes such as scheduling tasks, implementing timeouts, and synchronizing concurrent operations.
Uses of Timers
Some common use cases of timers in Go include the following:
- Scheduling Tasks – Timers allow us to schedule the tasks that can run at a specific time or various intervals.
- Implementing Timeouts – When you need to enforce the time limits on a given operation, timers will probably be your best bet. For example, you can use a timer to cancel a task if it takes too long to complete.
- Rate Limiting – We can also use timers to control the rate at which a specific action or request is allowed to occur.
- Concurrent Synchronization – Timers can help coordinate and synchronize the concurrent operations.
With that out of the way, let us dive into the meat of timers in Go.
Create a Timer in Golang
In Go, we can create a timer using the NewTimer() method from the “time” package. The function accepts a duration as the parameter as shown in the following syntax:
import (
"fmt"
"time"
)
func main() {
timer := time.NewTimer(2 * time.Second)
fmt.Println("Waiting for the timer to expire...")
<-timer.C
fmt.Println("Timer expired!")
}
In this example, we create a timer that expires after 2 seconds. We then wait for it to expire using the “<- timer.C”.
The “Timer” type represents a single event. When the Timer expires, the current time will be sent on C, unless the Timer was created by AfterFunc.
Reset a Timer in Golang
Go supports the ability to reset a timer to make it start counting again after a specific duration. This is incredibly useful when you need to reuse a timer without actually duplicating them.
An example is as follows:
import (
"fmt"
"time"
)
func main() {
timer := time.NewTimer(2 * time.Second)
timer.Reset(1 * time.Second)
fmt.Println("Waiting for the timer to expire...")
<-timer.C
fmt.Println("Timer expired!")
}
This should reset the timer after one second as defined in the timer.Reset() method.
Stop a Timer in Golang
We can stop a timer before it expires by calling the Timer.Stop() method. This prevents the timer from triggering its associated action.
An example code is as follows:
import (
"fmt"
"time"
)
func main() {
timer := time.NewTimer(5 * time.Second)
stopped := timer.Stop()
if stopped {
fmt.Println("Timer stopped before it expired")
} else {
fmt.Println("Timer already expired or stopped")
}
}
This should stop the timer after one second. This means that the 5 second timer will not elapse before termination.
Using a Select Statement with Timers
One of the most powerful and useful operation of timers in Go is pairing them with the Go “select” statement. This helps to handle multiple channels including timers in a concurrent manner.
NOTE: In Go, the role of the “select” statement is to enable us to wait for multiple channel operations and take actions based on the first one that becomes ready.
We can use timers with the “select” statement as shown in the following example:
import (
"fmt"
"time"
)
func main() {
timeout := time.NewTimer(5 * time.Second)
go func() {
time.Sleep(2 * time.Second)
}()
select {
case <-timeout.C:
fmt.Println("Operation timed out")
case <-time.After(4 * time.Second):
fmt.Println("Fallback: Operation took too long")
}
}
In this example, we create a timer with a five second timeout. We then use the “select” statement to handle either the timeout or a fallback case.
Periodic Timers with Ticker
The next thing that pairs well with timers is tickers. Tickers allows us to perform an action repeatedly at fixed intervals using the time.Ticker.
You can think of Ticker like a timer that automatically resets after each expiration.
import (
"fmt"
"time"
)
func main() {
ticker := time.NewTicker(1 * time.Second)
// repeat task
go func() {
for {
<-ticker.C
fmt.Println("Tick!")
}
}()
// run for 5 seconds
time.Sleep(5 * time.Second)
// Stop the ticker
ticker.Stop()
fmt.Println("Ticker stopped")
}
In the given example, we start by defining a task that we wish to repeat for specific intervals.
We then create a new Ticker that ticks every second and execute the previous task. We then stop using the ticker.Stop() method.
Running the previous code returns an example output as follows:
Tick!
Tick!
Tick!
Ticker stopped
Conclusion
In this tutorial, we explored quite a lot about timers in Go using the “time” package. We started with the basics of creating, resetting, and stopping the timers. We then learned about using timers with the “select” statements and learned about Tickers.