ProgrammierungGo Entwickler

Was muss man über die Arbeit mit time.Timer und time.Ticker in Go wissen? Was sind die wichtigsten Unterschiede, Besonderheiten der korrekten Verwendung und häufige Fehler beim Stoppen/Zurücksetzen?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort

Das Paket time bietet zwei nützliche Werkzeuge: Timer und Ticker.

  • Timer wird für eine einmalige Verzögerung verwendet (es wird einmal nach einer bestimmten Zeit ausgelöst).
  • Ticker — für regelmäßige periodische Ereignisse (Intervall).

Wesentliche Unterschiede:

  • Der Timer "geht aus", nachdem er ausgelöst wurde; er muss zurückgesetzt werden (Reset), um ihn erneut zu verwenden.
  • Der Ticker erzeugt Ereignisse, solange er nicht ausdrücklich mit der Methode Stop() gestoppt wird.

Besonderheiten der Verwendung:

  • Rufen Sie immer Stop() bei Timer/Ticker beim Beenden auf, um Ressourcenlecks zu vermeiden.
  • Nach dem Aufruf von Stop() bei Timer ist möglicherweise erforderlich, den Kanal "zu leeren": Wenn der Timer vor Stop() ausgelöst wurde, muss aus dem Kanal gelesen werden.

Beispiel für die korrekte Verwendung von Timer:

t := time.NewTimer(2 * time.Second) defer t.Stop() // unbedingt! select { case <-t.C: fmt.Println("Die Zeit ist um!") case <-otherDone: if !t.Stop() { <-t.C // Kanal leeren, falls nötig } }

Fangfrage

Kann man Timer sofort wiederverwenden, nachdem man einen Wert aus dem Kanal t.C erhalten hat? Was passiert, wenn man t.Stop() nicht aufruft?

Antwort: Der Timer sollte nicht sofort zurückgesetzt werden, ohne Stop() aufzurufen und möglicherweise aus dem Kanal zu lesen. Wenn t.Stop() nicht aufgerufen wird, könnte eine "tote" Goroutine zurückbleiben oder ein unerwarteter Trigger im nächsten Zyklus auftreten (der Kanal ist nicht geleert). Die richtige Verwendung: Rufen Sie Stop() auf, und wenn Stop() false zurückgibt, leeren Sie unbedingt den Kanal durch Lesen von t.C.

Beispiele für reale Fehler aufgrund mangelnden Wissens über die Feinheiten des Themas


Geschichte

In dem Benachrichtigungsdienst eines Startups wurden Timer verwendet, um Zustellversuche zurückzusetzen. Nach dem Auslösen wurden sie sofort ohne Stoppen zurückgesetzt — das Ergebnis: die Anzahl der Goroutinen wuchs, der Prozess "leckete", das System fiel wegen speicherknappheit aus.

Geschichte

In einem großen E-Commerce-Projekt wurde für die regelmäßige Aktualisierung von Produkten ein Ticker verwendet, der beim Beenden des Handlers nicht gestoppt wurde. Der Handler "hing" selbst nach der Löschung des Benutzers und verbrauchte weiterhin CPU.

Geschichte

In Tests wurde Stop() für den Timer nicht aufgerufen — die Tests hingen zufällig, weil der Timerkanal nicht freigegeben wurde, der zweite "Ping" vom Timer, der nie kam, wurde erwartet.