リーク検出とキャンセル
ゴルーチンが終了することを保証し、リークを防ぎます。
「リーク検出とキャンセル」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。
ゴルーチンリークとは
ゴルーチンリークは、ゴルーチンが開始されたものの終了しない場合に発生します。リークしたゴルーチンは時間とともに蓄積し、スタックメモリと CPU を消費し続け、最終的にはプロセスが強制終了される可能性があります。
よくあるリーク: チャネル受信のブロック
値が届くことのないチャネルの受信を待機するゴルーチンは、永久にブロックされます:
go func() {
v := <-ch // leaks if no sender and ch is never closed
use(v)
}()よくあるリーク: 完了シグナルがない
終了条件も done チャネルもない for ループ内のゴルーチンは、永久に実行され続けます:
go func() {
for {
work()
// no exit condition — leaks
}
}()goleak によるリークの検出
go.uber.org/goleak は、テストの終了時にゴルーチンがリークしていないことを検証します:
func TestMyFunc(t *testing.T) {
defer goleak.VerifyNone(t)
myFunc() // should not leak goroutines
}解決策としての Context
長時間実行されるゴルーチンを停止する慣用的な方法は context です。ゴルーチンに ctx を渡し、ctx.Done() を select で監視します。
go func(ctx context.Context) {
for {
select {
case work := <-workCh:
process(work)
case <-ctx.Done():
return // clean exit
}
}
}(ctx)Done チャネルパターン
context を使わない単純なケースでは、専用の done チャネルを使用します。そのチャネルを close すると、そこから読み取っているすべてのゴルーチンに停止を通知できます。
done := make(chan struct{})
go func() {
select {
case v := <-data: use(v)
case <-done: return
}
}()
close(done) // stops goroutineruntime による検出
ゴルーチン数を出力して、実行時の増加を検出します:
fmt.Println("goroutines:", runtime.NumGoroutine())HTTP サーバーのゴルーチン
net/http はリクエストごとのゴルーチンを自動的に管理し、リクエストが完了すると後始末します。ただし、後始末をせずにゴルーチンを起動するハンドラーでは、依然としてリークが発生する可能性があります。
リークのテスト
goleak を TestMain または各テストの defer として使用し、テストスイートを実行します。テスト本体の終了後に終了していないゴルーチンがあると、テストは失敗します。
func TestMain(m *testing.M) {
goleak.VerifyTestMain(m)
}Time.After によるリーク
ループ内の select で time.After を使用すると、反復ごとに新しいタイマーが作成され、そのタイマーが発火するまで GC の対象になりません。time.NewTimer と Reset に置き換えてください。
エラーを返すゴルーチンによるリーク
ゴルーチンがチャネルに結果を送信する想定なのに、エラーによって送信せずに早期リターンすると、受信側のゴルーチンは永久にブロックされます。すべての経路で、必ずチャネルに送信するか close してください。
クイックチェック
Go で長時間実行されるゴルーチンを停止する、最も慣用的な方法は何ですか
振り返り: リークの検出とキャンセル
要点:
- ゴルーチンリークは蓄積します。runtime.NumGoroutine() で監視してください
- テストで goleak を使うと、ゴルーチンリークを自動的に検出できます
- ゴルーチンには必ず終了経路を用意してください。context、done チャネル、または入力チャネルのクローズを使用します
- ループ内の time.After はタイマーをリークさせます。NewTimer+Reset を使用してください
よくある質問
「リーク検出とキャンセル」レッスンは無料ですか?
はい。「リーク検出とキャンセル」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。
「リーク検出とキャンセル」で何を学びますか?
ゴルーチンが終了することを保証し、リークを防ぎます。 ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Go Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「リーク検出とキャンセル」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このGo Academyレッスンでコードを書いて実行できますか?
はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- パイプラインとステージのパターン
- 並行エラー処理のためのerrgroup
- セマフォパターン
- リーク検出とキャンセル