Range Over Ticker In Go With Immediate First Tick
The Go standard library has a really cool type - Ticker. Tickers are used when you want to do something at a regular interval, similar to JavaScript’s setInterval. Here’s an example:
package main
import (
"fmt"
"time"
)
func main() {
ticker := time.NewTicker(time.Second)
go func() {
for range ticker.C {
fmt.Println("Tick")
}
}()
time.Sleep(time.Second * 4)
ticker.Stop()
fmt.Println("Ticker stopped")
}
As per the docs, a ticker is a struct that holds a receive-only channel of time.Time objects.
type Ticker struct {
C <-chan Time // The channel on which the ticks are delivered.
}
In the example at the beginning of the article, you will notice by running the program that the first tick sent over the channel happens after the first interval of time has elapsed. As such, if you are trying to build, for example, a rate limiter, it can be inconvenient because to get the first immediate execution, it would seem your best option is:
func doSomethingWithRateLimit() {
ticker := time.NewTicker(time.Second)
doSomething()
for range ticker.C {
doSomething()
}
}
There is in fact a better option!
In Go, a channel can also be iterated over in a normal for-loop, so our solution is to build a for loop that executes automatically on the first iteration, then waits for each subsequent loop.
package main
import (
"fmt"
"time"
)
func main() {
ticker := time.NewTicker(time.Minute)
for ; true; <-ticker.C {
fmt.Println("hi")
}
}
Hopefully this helps keep redundant code out of your projects!
Related Articles
Using 'Go Generate' To Deploy Multi-Process Apps
Apr 22, 2020 by Lane Wagner - Boot.dev co-founder and backend engineer
In microservice architectures, it’s fairly common to have a project that includes different worker types. A Makefile can be used to manage the creation of multiple programs, but the Go toolchain has a tool that can be used as well, go generate. Here are some examples of how it can be used:
What Are Golang's Anonymous Structs?
Apr 21, 2020 by Lane Wagner - Boot.dev co-founder and backend engineer
An anonymous struct is just like a normal struct, but it is defined without a name and therefore cannot be referenced elsewhere in the code.
Announcing Go-TinyTime, Go-TinyDate's Sister Package
Apr 02, 2020 by Lane Wagner - Boot.dev co-founder and backend engineer
time.Time is the perfect choice for handling times in Go in most cases, it even comes in the standard library! The problem is that the time.Time{} struct uses more than 24 bytes of memory under most conditions. Go-TinyTime solves this problem by restricting the available dates to the range between 1970 - 2106, and only supporting UTC timezones. This brings data usage down to just 4 bytes of memory.
Golang Conversions - Ints To Strings And Strong Typing
Mar 31, 2020 by Lane Wagner - Boot.dev co-founder and backend engineer
Go is a strongly typed language, which means at any point a developer should know exactly what type of value they are dealing with. For example, if we have a function that prints a string, we can’t just give it an integer and expect it to work. We have to cast it to a string explicitly: