ProgrammingGo開発者

Goにおけるtime.Timerとtime.Tickerの操作について知っておくべきことは何ですか?主要な違いや正しい使い方のポイント、stop/reset時の一般的なエラーは何ですか?

Hintsage AIアシスタントで面接を突破

回答

timeパッケージは、非常に便利な2つのツールであるTimerTickerを提供します。

  • Timerは、単発の遅延(指定された時間後に1回だけ発動)に使用されます。
  • Tickerは、定期的なイベント(間隔)に使用されます。

主な違い:

  • Timerは発動後に「消えてしまう」ため、もう一度使用するにはリセットする必要があります(Reset)。
  • Tickerは、明示的にStop()メソッドで停止されるまでイベントを生成し続けます。

使用のポイント:

  • リソースリークを避けるために、作業が終了した際は必ずTimer/TickerStop()を呼び出してください。
  • TimerStop()を呼び出した後、チャンネルを「排水」する必要がある場合があります:タイマーがStop()前に発動していた場合、チャンネルからの読み出しは必須です。

Timerの正しい使用例:

t := time.NewTimer(2 * time.Second) defer t.Stop() // 必ず呼び出す! select { case <-t.C: fmt.Println("Time's up!") case <-otherDone: if !t.Stop() { <-t.C // チャンネルを排水する必要がある場合 } }

意地悪な質問

Timerのチャンネルt.Cから値を受け取った後、すぐに再使用することはできますか?t.Stop()を呼び出さなかった場合、何が起こりますか?

回答: タイマーは、Stop()を呼び出し、チャンネルからの読み出しを行わずに即座にリセットするべきではありません。t.Stop()を呼び出さなかった場合、「死んだ」ゴルーチンが残るか、次のサイクルで予期しないトリガーが発生する可能性があります(チャンネルがクリアされていないため)。正しい使用法は、Stop()を呼び出し、もしStop()がfalseを返した場合は、必ずt.Cからの読み出しでチャンネルを排水してください。

トピックに関する実際のエラーの事例


物語

スタートアップの通知サービスでは、配信試行をリセットするためにタイマーが使用されていました。発動後、停止せずにすぐにリセットしてしまい、その結果、ゴルーチンのスレッドが増加し、プロセスが「漏れ」、システムがメモリ不足でダウンしました。

物語

大規模なeコマースプロジェクトでは、製品の定期的な更新のためにTickerが使用されていましたが、ハンドラーの終了時に停止されませんでした。ハンドラーはユーザーの削除後も「ぶら下がり」、CPUを消費し続けました。

物語

テストではタイマーのStop()を呼び出さず、チャンネルが解放されずにタイマーからの2回目の「ピング」を待つためにテストがランダムにフリーズしました。