MeWrite Docs

Go: context canceled

GoでContextがキャンセルされた際のエラー原因と解決策

概要

GoのContextがキャンセルまたはタイムアウトした際に発生するエラーです。

エラーメッセージ

``` context canceled context deadline exceeded ```

原因

  1. 明示的なキャンセル: cancel()の呼び出し
  2. タイムアウト: context.WithTimeoutの期限切れ
  3. 親コンテキストのキャンセル: 親がキャンセルされると子も連動
  4. HTTPリクエストの中断: クライアントが接続を切断

解決策

1. Contextを適切に伝播

```go func handler(w http.ResponseWriter, r *http.Request) { ctx := r.Context()

result, err := doWork(ctx)
if err != nil {
    if errors.Is(err, context.Canceled) {
        // クライアントが切断した
        return
    }
    http.Error(w, err.Error(), 500)
    return
}

json.NewEncoder(w).Encode(result)

}

func doWork(ctx context.Context) (Result, error) { select { case <-ctx.Done(): return Result{}, ctx.Err() case result := <-workChan: return result, nil } } ```

2. タイムアウトを設定

```go ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel()

// HTTPリクエスト req, _ := http.NewRequestWithContext(ctx, “GET”, url, nil) resp, err := client.Do(req) if err != nil { if errors.Is(err, context.DeadlineExceeded) { log.Println(“Request timed out”) } return err } ```

3. グレースフルシャットダウン

```go func main() { ctx, cancel := context.WithCancel(context.Background())

// シグナルハンドリング
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

go func() {
    <-sigChan
    cancel()
}()

if err := run(ctx); err != nil && !errors.Is(err, context.Canceled) {
    log.Fatal(err)
}

} ```

4. データベースクエリでの使用

```go ctx, cancel := context.WithTimeout(ctx, 3*time.Second) defer cancel()

rows, err := db.QueryContext(ctx, “SELECT * FROM users WHERE id = ?”, id) if err != nil { if errors.Is(err, context.DeadlineExceeded) { return nil, fmt.Errorf(“query timed out: %w”, err) } return nil, err } ```

よくある間違い

  • defer cancel() を忘れてリソースリーク
  • context.Background() を常に使う
  • エラーの種類を確認しない

関連エラー

関連エラー

Go の他のエラー

最終更新: 2025-12-10