Go

How would you implement rate limiting using channels?

Question 214MediumGo 1.22 to 1.25
// Token bucket: burst of 5, refill 10/s
func NewLimiter(ctx context.Context, rate time.Duration, burst int) <-chan struct{} {
	tokens := make(chan struct{}, burst)
	for range burst {
		tokens <- struct{}{}
	}
	go func() {
		t := time.NewTicker(rate)
		defer t.Stop()
		for {
			select {
			case <-ctx.Done():
				return
			case <-t.C:
				select {
				case tokens <- struct{}{}: // refill
				default: // bucket full, drop token
				}
			}
		}
	}()
	return tokens
}

lim := NewLimiter(ctx, 100*time.Millisecond, 5)
for _, req := range requests {
	<-lim // wait for a token
	go handle(req)
}

The buffered channel is the bucket, the ticker refills it, and a non-blocking send drops overflow tokens so the burst stays capped. Interviewers expect you to mention that golang.org/x/time/rate (rate.NewLimiter(r, b) with Wait(ctx)) is the production choice. It needs no goroutine, handles fractional rates, and supports reservations, whereas the ticker version costs a goroutine and wakes up even when idle.

More on Channels & select

All 38 Channels & select questions