time.After
Use `time.After` for simple one-shot waits, not hot loops where timer allocation and cleanup behavior matter.
Canonical guidance
time.Afteris fine for simple one-off waits- prefer
time.NewTimerwhen timeouts repeat or need cleanup control - stop timers you no longer need
Use when
- one-shot
selecttimeouts - tests or tiny helpers
- code where timer reuse is irrelevant
Avoid
time.Afterinside long-running loops- creating fresh timers on every iteration without control
- assuming timeout channels can be canceled after creation
Preferred pattern
timer := time.NewTimer(timeout)
defer timer.Stop()
select {
case <-done:
return nil
case <-timer.C:
return context.DeadlineExceeded
}
Anti-pattern
selectloops that create a newtime.Afteron every pass
Explanation: This anti-pattern is tempting because it is short, but repeated one-shot timer creation obscures lifecycle costs and cancellation behavior.
Why
- explicit timers make repeated timeout paths easier to reason about
Related pages
Sources
- time package - Go Team
- time.After and memory leaks (#76) - Teiva Harsanyi