Golang / GoLang Concurrency Mastery Interview Questions
What are the differences between time.After, time.NewTimer, and time.NewTicker, and which leaks resources?
All three involve time-based channel operations but have distinct behaviours, reuse capabilities, and resource management responsibilities.
| API | Returns | Fires | Resource leak risk | Reusable |
|---|---|---|---|---|
| time.After(d) | <-chan Time | Once, after d | Goroutine + channel until d expires if case not taken | No |
| time.NewTimer(d) | *time.Timer | Once, after d | Must call Stop() | Yes (via Reset) |
| time.NewTicker(d) | *time.Ticker | Every d forever | MUST call Stop() — goroutine lives until Stop or process exit | Yes (until stopped) |
// time.After â convenient but leaks if the receive case is not taken select { case result := <-doWork(): fmt.Println(result) case <-time.After(5 * time.Second): fmt.Println("timeout") // If doWork wins: timer goroutine and channel live for 5s â avoid in loops } // time.NewTimer â correct approach for loops or where early stop is needed timer := time.NewTimer(5 * time.Second) defer timer.Stop() // always stop select { case result := <-doWork(): timer.Stop() fmt.Println(result) case <-timer.C: fmt.Println("timeout") } // time.NewTicker â periodic work, must stop ticker := time.NewTicker(1 * time.Second) defer ticker.Stop() // MUST stop â goroutine lives until Stop() called for { select { case <-ticker.C: doPeriodicWork() case <-ctx.Done(): return } } // Production: context.WithTimeout is preferred for request deadlines ctx, cancel := context.WithTimeout(parentCtx, 5*time.Second) defer cancel()
More Related questions...