Time Tick Leak

ID

go.time_tick_leak

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Go

Tags

performance, reliability

Description

Reports time.Tick(…​) used as the iterator of a for …​ range loop, for example for x := range time.Tick(d).

Rationale

time.Tick returns only the channel of an internal time.Ticker; the ticker itself is never returned, so it can never be stopped. Ranging over that channel keeps the ticker and its driving goroutine alive for the entire lifetime of the program, even after the loop is abandoned — a resource leak the standard library documentation explicitly warns about. time.NewTicker returns the ticker, whose Stop method releases it.

for now := range time.Tick(time.Second) { // FLAW — the ticker can never be stopped
    use(now)
}

ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for now := range ticker.C {                 // OK
    use(now)
}

Remediation

Replace time.Tick with time.NewTicker, range over its C channel, and call Stop (for example with defer ticker.Stop()) when the loop is done.