go-context について
go-contextは、Goでcontextを使う際のAPI慣習と一般的なパターンをまとめたガイドです。リクエストコンテキスト、キャンセル、期限を扱う開発者向けに、context.Contextの明示的な受け渡しと値の用途を説明します。
主な機能
- 01関数の第1引数にContextを指定
- 02構造体へのContext保存を避ける指針
- 03派生コンテキストとキャンセル処理
- 04コンテキスト値の適切な用途
活用シーン
- 01リクエストコンテキストを受け取る関数の設計
- 02期限とキャンセル処理の実装
- 03リクエストデータをコンテキスト値に置くか判断
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ cxuu/ golang-skills --skill go-contextインストール後、Claude Code で/go-contextを入力して読み込まれたか確認します。
同梱ファイルreferences/PATTERNS.md
詳細
Go Context の使用
互換性:
contextは Go 1.7 から標準ライブラリに含まれています。
リソースのルーティング
references/PATTERNS.md- コンテキストを派生させる場合、キャンセルを確認する場合、HTTP リクエストのコンテキストを処理する場合、または型付きのコンテキスト値キーを使用する場合に読みます。
Context を最初の引数にする
Context を使用する関数は、Context を最初の引数として受け取る必要があります。
func F(ctx context.Context, /* other arguments */) error
func ProcessRequest(ctx context.Context, req *Request) (*Response, error)
これは Go における確立された慣習であり、コードベース全体でコンテキストの流れを見やすく、一貫性のあるものにします。
Context を構造体に保存しない
構造体型に Context メンバーを追加しないでください。代わりに、必要とする各メソッドに ctx をパラメーターとして渡します。
// Bad: Context stored in struct
type Worker struct {
ctx context.Context // Don't do this
}
// Good: Context passed to methods
type Worker struct{ /* ... */ }
func (w *Worker) Process(ctx context.Context) error {
// Context explicitly passed — lifetime clear
}
例外:標準ライブラリまたはサードパーティーライブラリのインターフェースにシグネチャーを一致させる必要があるメソッドでは、回避策が必要になる場合があります。
カスタム Context 型を作成しない
カスタム Context 型を作成したり、関数シグネチャーで context.Context 以外のインターフェースを使用したりしないでください。
// Bad: Custom context type
type MyContext interface {
context.Context
GetUserID() string
}
// Good: Use standard context.Context with value extraction
func Process(ctx context.Context) error {
userID := GetUserID(ctx)
}
アプリケーションデータの格納先
以下の選択肢を、優先度の高い順に検討してください。
- 関数パラメーター — 最も明示的で、型安全です
- レシーバー — 型に属するデータに使用します
- グローバル変数 — 真にグローバルな設定に使用します(必要最小限にしてください)
- コンテキスト値 — リクエストスコープのデータにのみ使用します
コンテキスト値の使用が適切なもの:
- リクエスト ID とトレース ID
- リクエストに伴って渡される認証/認可情報
- デッドラインとキャンセルシグナル
コンテキスト値の使用が適切でないもの:
- 任意の関数パラメーター
- 明示的に渡せるデータ
- リクエストごとに変わらない設定
一般的なパターン
コンテキストの派生
派生コンテキストの作成直後に、必ず defer cancel() を実行します。
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
キャンセルの確認
select {
case <-ctx.Done():
return ctx.Err()
default:
// Do work
}
Context の不変性
コンテキストは不変です。同じデッドラインとキャンセルシグナルを共有する複数の並行呼び出しに、同じ ctx を安全に渡せます。
関連スキル
- ゴルーチンの連携:ゴルーチンのキャンセル、select ベースのタイムアウト、または errgroup に Context を使用する場合は、go-concurrency を参照してください
- エラー処理:
ctx.Err()のキャンセルエラーをどのようにラップまたは返すかを決める場合は、go-error-handling を参照してください - インターフェース設計:インターフェースとともに Context を受け取る API を設計する場合は、go-interfaces を参照してください
- リクエストスコープのロギング:ロガーをコンテキストに挿入する場合や、構造化ログ出力にリクエスト ID を追加する場合は、go-logging を参照してください
コメント
Markdown 対応