ProgrammingGo Developer

What should you know about working with time.Timer and time.Ticker in Go? What are the key differences, features of correct usage, and common mistakes when stopping/resetting them?

Pass interviews with Hintsage AI assistant

Answer

The time package provides two useful tools: Timer and Ticker.

  • Timer is used for a single delay (it triggers once after a specified time).
  • Ticker is for regular periodic events (interval).

Key differences:

  • Timer 'turns off' after it triggers, it needs to be reset (Reset) to be used again.
  • Ticker generates events until explicitly stopped using the Stop() method.

Usage features:

  • Always call Stop() for Timer/Ticker when you are done to avoid resource leaks.
  • After calling Stop() on a Timer, it may be necessary to "drain" the channel: if the timer fired before Stop(), reading from the channel is mandatory.

Example of correct Timer usage:

t := time.NewTimer(2 * time.Second) defer t.Stop() // mandatory! select { case <-t.C: fmt.Println("Time's up!") case <-otherDone: if !t.Stop() { <-t.C // drain the channel if needed } }

Trick question

Can a Timer be reused immediately after receiving a value from the channel t.C? What happens if you don't call t.Stop()?

Answer: The timer should not be immediately reset without calling Stop() and possibly reading from the channel. If t.Stop() is not called, it may leave a "dead" goroutine or trigger unexpectedly in the next cycle (the channel is not cleared). Correct usage: call Stop(), and if Stop() returns false — definitely drain the channel by reading from t.C.

Examples of real mistakes due to ignorance of the nuances of the topic


Story

In the notification service of a startup, timers were used to reset delivery attempts. After they triggered, they were immediately reset without stopping — the result: the number of goroutines increased, the process "leaked", and the system crashed due to memory shortage.

Story

In a large e-commerce project, a Ticker was used for periodic product updates, which was not stopped upon handler completion. The handler "hung" even after the user was deleted, continuing to consume CPU.

Story

In tests, Stop() was not called for the timer — tests hung randomly because the timer's channel was not freed, waiting for a second "ping" from the timer, which never came.