0Pricing
Go Academy · レッスン

WithDeadlineとWithValue

絶対的なデッドラインとリクエストスコープの値の受け渡し

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

context.WithDeadline

WithDeadlineは、絶対時刻にキャンセルされるcontextを作成します。親にすでにそれより早いデッドラインがある場合は、親のデッドラインが優先されます。

deadline := time.Now().Add(10 * time.Second)
ctx, cancel := context.WithDeadline(parent, deadline)
defer cancel()

WithTimeout と WithDeadline の比較

WithTimeout(parent, d) は、WithDeadline(parent, time.Now().Add(d)) と同等です。絶対的な有効期限がある場合(受信した RPC ヘッダーから取得した場合など)は、WithDeadline を使用します。

デッドラインの読み取り

ctx.Deadline() を使うと、任意のコンテキストのデッドラインを調べられます。戻り値のブール値は、デッドラインが存在するかどうかを示します。

if deadline, ok := ctx.Deadline(); ok {
    fmt.Println("expires at:", deadline)
}

context.WithValue

WithValue は、キーと値のペアをコンテキストに付加します。下流のコードでは ctx.Value(key) を使って取得できます。

type ctxKey string
const userKey ctxKey = "user"

ctx := context.WithValue(parent, userKey, currentUser)

func getUser(ctx context.Context) *User {
    u, _ := ctx.Value(userKey).(*User)
    return u
}

キーの衝突防止

パッケージ間での衝突を防ぐため、キーにはエクスポートしないパッケージ固有の型を使用します。組み込み型(string や int)をコンテキストキーとして直接使用してはいけません。

// Bad: string key can collide
ctx = context.WithValue(ctx, "user", u)
// Good: package-scoped type
type userKeyType struct{}
ctx = context.WithValue(ctx, userKeyType{}, u)

コンテキストに保存するもの

API の境界をまたぐリクエスト単位の値だけを保存します。たとえば、トレース ID、認証トークン、リクエスト ID などです。省略可能な関数引数や可変状態は保存しないでください。

WithValue のパフォーマンス

ctx.Value はコンテキストチェーンを上方向に線形検索します。1 つのコンテキストに多くの値を保存することは避け、複数の値がある場合は 1 つの構造体にまとめてください。

type RequestMeta struct {
    UserID  int
    TraceID string
}
type metaKey struct{}
ctx = context.WithValue(ctx, metaKey{}, RequestMeta{...})

ミドルウェアによる値の伝播

HTTP ミドルウェアは、リクエストメタデータをコンテキストに付加し、ハンドラーで取得するための標準的な場所です。

func Auth(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        user := authenticate(r)
        ctx := context.WithValue(r.Context(), userKey, user)
        next.ServeHTTP(w, r.WithContext(ctx))
    })
}

r.WithContext

r.WithContext(ctx) を使って、HTTP リクエストのコンテキストを置き換えます。これにより新しいコンテキストを持つリクエストのシャローコピーが作成され、元のリクエストは変更されません。

デッドラインの伝播

ゲートウェイがコンテキストにデッドラインを設定してリクエストを下流に渡すと、コンテキストを受け取るすべてのサービスが、明示的なタイムアウト処理なしで自動的にそのデッドラインに従います。

コンテキストのチェーン

WithValue、WithCancel、WithTimeout はそれぞれ、親コンテキストを新しいノードでラップします。ctx.Value はキーが見つかるか、nil を返すルートコンテキストに到達するまでチェーンをたどります。

クイックチェック

コンテキストキーに、エクスポートしないパッケージ固有の型を使うべきなのはなぜですか。

まとめ: WithDeadline と WithValue

要点:

  • WithDeadline は絶対時刻でキャンセルし、WithTimeout は相対時間でキャンセルします
  • ctx.Deadline() でデッドラインを読み取ります
  • WithValue はリクエスト単位のメタデータに使用し、型付きのエクスポートしないキーを使います
  • チェーンの深さを減らすため、複数の値を構造体にまとめます

よくある質問

「WithDeadlineとWithValue」レッスンは無料ですか?

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

「WithDeadlineとWithValue」で何を学びますか?

絶対的なデッドラインとリクエストスコープの値の受け渡し ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

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

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

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

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

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

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

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

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