Go Academy · レッスン

WithCancelとWithTimeout

キャンセル可能なコンテキストと時間制限付きコンテキストを作成します。

レッスン 2/413 ステップ

「WithCancelとWithTimeout」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。

context.WithCancel

WithCancelは、キャンセル関数を持つ新しいcontextを派生させます。cancelを呼び出すと、派生したcontextとそのすべての子のDoneチャネルがクローズされます。

ctx, cancel := context.WithCancel(parent)
defer cancel() // always call to release resources
go doWork(ctx)

必ずcancelをdeferする

cancelを呼び出さないと、親contextを監視するゴルーチンがリークします。キャンセル可能なcontextを作成した直後に、必ずcancelをdeferしてください。

context.WithTimeout

WithTimeoutは、指定された期間が経過した後に自動的にキャンセルされるcontextを派生させます。これはWithDeadlineの便利なラッパーです。

ctx, cancel := context.WithTimeout(parent, 5*time.Second)
defer cancel()
if err := db.QueryContext(ctx, query); err != nil {
    // err may be context.DeadlineExceeded
}

Err()の確認

Doneがクローズされた後、ctx.Err()は理由を返します。明示的にキャンセルされた場合はcontext.Canceled、タイムアウトした場合はcontext.DeadlineExceededです。

if err := ctx.Err(); errors.Is(err, context.DeadlineExceeded) {
    log.Println("timeout")
}

別のゴルーチンからキャンセルする

cancel関数は、どのゴルーチンから呼び出しても安全であり、複数のゴルーチンから同時に呼び出すこともできます。効果があるのは最初の呼び出しだけです。

ctx, cancel := context.WithCancel(context.Background())
go func() {
    if detectError() { cancel() }
}()

HTTPリクエストのタイムアウト

受け取ったリクエストのcontextにWithTimeoutを使用して、リクエストごとのタイムアウトを設定します。

func handler(w http.ResponseWriter, r *http.Request) {
    ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)
    defer cancel()
    result, err := service.Call(ctx)
    // ...
}

連鎖的なキャンセル

親contextがキャンセルされると、派生したすべてのcontext(子や孫)も自動的にキャンセルされ、呼び出しツリー内のすべてのゴルーチンが停止します。

テストでのContext

テストが開始したゴルーチンに時間制限を設けるため、テストではcontext.Background()またはcontext.WithTimeoutを使用します。

ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
testResult := runTest(ctx)

ライブラリを通じたcontextの伝播

受け取ったcontextは、外部への呼び出し(DBクエリ、HTTP呼び出し、RPC)に必ず渡してください。デッドラインをリセットする明確な理由がない限り、破棄したり置き換えたりしないでください。

バックグラウンドジョブ用のcontextの作成

リクエストに紐づかないバックグラウンドジョブでは、ルートとしてcontext.Background()を使用し、WithCancelを追加してジョブを適切に停止できるようにします。

Doneを使ったselect

contextが処理の完了前にキャンセルされた場合にもブロックしないよう、作業用チャネルとともにctx.Done()も必ずselectします。

select {
case result := <-workCh:
    return result, nil
case <-ctx.Done():
    return nil, ctx.Err()
}

確認問題

context.WithCancelとcontext.WithTimeoutの違いは何ですか。

まとめ: WithCancelとWithTimeout

要点:

  • 作成直後に必ずcancel()をdeferします
  • WithTimeoutは指定期間後に自動キャンセルし、DeadlineExceededを返します
  • ctx.Err()でCanceledとDeadlineExceededを区別できます
  • キャンセルはすべての派生contextに伝播します
無料で開始

AI チューターと学ぶ Go — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
51
レッスン
203

よくある質問

「WithCancelとWithTimeout」レッスンは無料ですか?

はい。「WithCancelとWithTimeout」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。

「WithCancelとWithTimeout」で何を学びますか?

キャンセル可能なコンテキストと時間制限付きコンテキストを作成します。 ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Go Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「WithCancelとWithTimeout」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このGo Academyレッスンでコードを書いて実行できますか?

はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

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

  1. context.Contextが存在する理由
  2. WithCancelとWithTimeout
  3. WithDeadlineとWithValue
  4. HTTPとデータベース呼び出しにおけるContext
← Go Academyに戻る