How to Implement Rate Limiter in Go: Simple Guide with Example
In Go, you can implement a rate limiter using
time.Ticker to control how often actions happen by sending ticks at fixed intervals. By combining time.Ticker with channels, you can limit the rate of requests or events easily and efficiently.Syntax
A basic rate limiter in Go uses time.Ticker which sends a signal on a channel at regular intervals. You listen to this channel to allow actions only when a tick arrives.
time.NewTicker(duration): creates a ticker that ticks everyduration.ticker.C: channel that receives a tick at each interval.- Use a
forloop withrange ticker.Cto perform actions at the limited rate.
go
ticker := time.NewTicker(time.Second) // ticks every 1 second for range ticker.C { // perform limited action here }
Example
This example shows a rate limiter that allows printing a message only once every 500 milliseconds, simulating a controlled request flow.
go
package main import ( "fmt" "time" ) func main() { ticker := time.NewTicker(500 * time.Millisecond) // tick every 500ms defer ticker.Stop() for i := 1; i <= 5; i++ { <-ticker.C // wait for tick fmt.Printf("Request %d processed at %v\n", i, time.Now().Format("15:04:05.000")) } }
Output
Request 1 processed at 12:00:00.500
Request 2 processed at 12:00:01.000
Request 3 processed at 12:00:01.500
Request 4 processed at 12:00:02.000
Request 5 processed at 12:00:02.500
Common Pitfalls
Common mistakes when implementing rate limiters in Go include:
- Not stopping the ticker with
ticker.Stop(), which can cause resource leaks. - Blocking on ticker channel without timeout or context, causing deadlocks.
- Using
time.Sleepinstead oftime.Ticker, which is less efficient and less flexible.
Always use defer ticker.Stop() to clean up and consider using select with context for cancellation.
go
package main import ( "fmt" "time" ) func main() { // Wrong: ticker not stopped ticker := time.NewTicker(time.Second) for i := 0; i < 3; i++ { <-ticker.C fmt.Println("Action", i) } // Missing ticker.Stop() can cause resource leak // Right way: // ticker := time.NewTicker(time.Second) // defer ticker.Stop() }
Quick Reference
| Concept | Description |
|---|---|
| time.NewTicker(duration) | Creates a ticker that sends ticks at the given interval |
| ticker.C | Channel that receives ticks to trigger actions |
| ticker.Stop() | Stops the ticker to release resources |
| <-ticker.C | Waits for the next tick before proceeding |
| Use defer ticker.Stop() | Ensure ticker is stopped to avoid leaks |
Key Takeaways
Use time.Ticker to send ticks at fixed intervals for rate limiting.
Always stop your ticker with defer ticker.Stop() to avoid resource leaks.
Wait on ticker.C channel to control when actions happen.
Avoid blocking indefinitely by using context or select with ticker.
time.Ticker is more efficient and flexible than time.Sleep for rate limiting.