0Pricing
Go Academy · レッスン

リーク検出とキャンセル

ゴルーチンが終了することを保証し、リークを防ぎます。

「リーク検出とキャンセル」は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 goroutine

runtime による検出

ゴルーチン数を出力して、実行時の増加を検出します:

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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. パイプラインとステージのパターン
  2. 並行エラー処理のためのerrgroup
  3. セマフォパターン
  4. リーク検出とキャンセル
← Go Academyに戻る