カテゴリ: Go言語 更新日: 2025/12/21

Go言語のcontextパッケージを活用したキャンセル処理の基本を徹底解説!初心者でもわかるgoroutineの安全な終了方法

Go言語のcontextパッケージを活用したキャンセル処理の基本
Go言語のcontextパッケージを活用したキャンセル処理の基本

先生と生徒の会話形式で理解しよう

生徒

「先生、Go言語で長時間動く処理を止めたいときはどうすればいいんですか?たとえば、APIの呼び出しとか、goroutineがずっと動き続けてしまうときです。」

先生

「とても大事なポイントですね。そんなときに使うのが、context(コンテキスト)パッケージです。これは、処理の“キャンセル”や“タイムアウト”を簡単に管理するための仕組みなんです。」

生徒

「なるほど。つまり、goroutineを安全に止められるってことですか?」

先生

「その通りです。では、Goのcontextを使って、キャンセル処理の基本をわかりやすく説明していきましょう。」

1. contextパッケージとは?

1. contextパッケージとは?
1. contextパッケージとは?

context(コンテキスト)とは、Go言語で「処理の状態を共有するための仕組み」です。特に、キャンセルやタイムアウトをgoroutine全体に伝えるために使われます。

例えば、Webサーバーでリクエストを処理しているとき、ユーザーが途中でページを閉じたら、そのリクエスト処理を止めたいですよね。そんなときにcontextが役立ちます。

つまり、contextを使うと「処理をやめる合図」をgoroutineに伝えることができるのです。

2. contextの基本構造

2. contextの基本構造
2. contextの基本構造

Go言語のcontextには、以下のような種類があります。

  • context.Background():一番基本となる空のコンテキスト。
  • context.WithCancel():キャンセル機能を追加する。
  • context.WithTimeout():一定時間で自動キャンセル。
  • context.WithDeadline():指定時刻でキャンセル。

これらを使い分けることで、処理の制御がとても簡単になります。では、実際にWithCancelを使って、goroutineをキャンセルしてみましょう。

3. context.WithCancelの使い方

3. context.WithCancelの使い方
3. context.WithCancelの使い方

WithCancelは、手動でキャンセルできるcontextを作る関数です。まずはサンプルコードを見てください。


package main

import (
    "context"
    "fmt"
    "time"
)

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

    go func() {
        for {
            select {
            case <-ctx.Done():
                fmt.Println("処理を中断しました")
                return
            default:
                fmt.Println("goroutine実行中...")
                time.Sleep(500 * time.Millisecond)
            }
        }
    }()

    time.Sleep(2 * time.Second)
    cancel() // キャンセルを呼び出す
    time.Sleep(1 * time.Second)
}

このコードでは、cancel()を呼ぶことで、goroutineにキャンセルの合図を送っています。goroutineはctx.Done()を受け取ると処理を止めます。


goroutine実行中...
goroutine実行中...
goroutine実行中...
goroutine実行中...
処理を中断しました

このように、キャンセルを安全に伝えることで、無限ループのような処理でも安全に停止できます。

4. context.WithTimeoutで自動キャンセル

4. context.WithTimeoutで自動キャンセル
4. context.WithTimeoutで自動キャンセル

今度は、一定時間が経ったら自動でキャンセルされるWithTimeoutを使ってみましょう。手動でキャンセルを呼ばなくても、自動で処理を止めることができます。


package main

import (
    "context"
    "fmt"
    "time"
)

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    defer cancel()

    go func() {
        for {
            select {
            case <-ctx.Done():
                fmt.Println("タイムアウトにより終了")
                return
            default:
                fmt.Println("処理中...")
                time.Sleep(500 * time.Millisecond)
            }
        }
    }()

    time.Sleep(3 * time.Second)
}

このコードでは、2秒経過すると自動的にキャンセルされます。プログラムが勝手に止まるような動きを作れるため、外部APIなど「待ち時間が長い処理」に向いています。


処理中...
処理中...
処理中...
タイムアウトにより終了

5. contextを使う理由とメリット

5. contextを使う理由とメリット
5. contextを使う理由とメリット

contextを使うことで、複数のgoroutineをまとめて管理できるという大きな利点があります。

  • 親goroutineがキャンセルすると、すべての子goroutineに通知される
  • タイムアウトや終了タイミングを統一できる
  • ネットワーク処理・API通信で安全なキャンセルが可能

もしcontextを使わないと、goroutineが止まらず、メモリを無駄に消費することになります。大規模なシステムでは、このような「停止制御」が非常に重要です。

6. contextのキャンセル伝播(親子関係)

6. contextのキャンセル伝播(親子関係)
6. contextのキャンセル伝播(親子関係)

contextは親子関係を持つことができます。つまり、親contextをキャンセルすると、その子contextも自動的にキャンセルされます。


package main

import (
    "context"
    "fmt"
    "time"
)

func main() {
    parent, cancel := context.WithCancel(context.Background())
    child, _ := context.WithCancel(parent)

    go func() {
        <-child.Done()
        fmt.Println("子contextもキャンセルされました")
    }()

    time.Sleep(time.Second)
    cancel() // 親をキャンセル
    time.Sleep(time.Second)
}

このように、親がキャンセルされると、子も自動で終了します。複数の処理をまとめて停止したいときに便利な仕組みです。

7. 実務での活用例

7. 実務での活用例
7. 実務での活用例

contextは、特にWebアプリケーションやAPIサーバーでよく使われます。たとえば、net/httpパッケージでは、リクエストごとに自動でcontextが生成されます。

ユーザーがページを閉じたらリクエスト処理がキャンセルされる仕組みも、実はcontextで実現されています。これにより、不要な処理を自動で止め、サーバーのリソースを節約できます。

カテゴリの一覧へ
新着記事
New1
Go言語
Go言語のオブジェクト指向の特徴を完全ガイド!初心者でも理解できる他言語との違い
New2
Go言語
Go言語の条件分岐の見やすい書き方を徹底解説!初心者でもわかるif文の使い方
New3
Kotlin
Kotlinのクラス設計に役立つベストプラクティスまとめ|初心者でもわかるクラス設計の考え方
New4
Kotlin
Kotlinでアーキテクチャ設計の基本!MVC・MVP・MVVMの違いを解説
人気記事
No.1
Java&Spring記事人気No1
Go言語
Go言語の関数パラメータ!値渡しと参照渡しの違いを理解しよう
No.2
Java&Spring記事人気No2
Swift
Swift Playgroundの使い方を完全解説!初心者に最適な学習環境の始め方
No.3
Java&Spring記事人気No3
Swift
Swift開発環境の構築方法を徹底解説!Xcode・Windows・Linux対応
No.4
Java&Spring記事人気No4
Kotlin
Gradleファイル(build.gradle.kts)の書き方と役割をやさしく解説!Kotlin初心者向け完全ガイド
No.5
Java&Spring記事人気No5
Kotlin
Kotlinのインストール方法まとめ!Windows・Mac・Linux別にステップ解説
No.6
Java&Spring記事人気No6
Kotlin
Kotlinの演算子一覧と使い方!算術・比較・論理演算子の基本を解説
No.7
Java&Spring記事人気No7
Go言語
Go言語のWebアプリにおけるセキュリティベストプラクティス集
No.8
Java&Spring記事人気No8
Kotlin
Android Studioのインストール手順と初期設定を初心者向けに完全解説!