Go バイ エグザンプル: コンテキスト

以前の例では、シンプルなHTTP サーバーの設定について説明しました。HTTP サーバーは、キャンセルの制御に `context.Context` を使用する方法を示すのに便利です。`Context` は、期限、キャンセル シグナル、その他の要求スコープ値を、API の境界やゴルーチン間で伝達します。

package main
import (
    "fmt"
    "net/http"
    "time"
)
func hello(w http.ResponseWriter, req *http.Request) {

`context.Context` は、`net/http` マシナリーによって各要求に対して作成され、`Context()` メソッドで利用できます。

    ctx := req.Context()
    fmt.Println("server: hello handler started")
    defer fmt.Println("server: hello handler ended")

クライアントに返信を送信する前に数秒待機します。これは、サーバーが一部作業を行っていることをシミュレーションできます。作業している間、コンテキストの `Done()` チャネルに注意して、作業をキャンセルし、できるだけ早く戻す必要があるというシグナルを監視します。

    select {
    case <-time.After(10 * time.Second):
        fmt.Fprintf(w, "hello\n")
    case <-ctx.Done():

コンテキストの `Err()` メソッドは、`Done()` チャネルがクローズされた理由を説明するエラーを返します。

        err := ctx.Err()
        fmt.Println("server:", err)
        internalError := http.StatusInternalServerError
        http.Error(w, err.Error(), internalError)
    }
}
func main() {

以前と同様、`"/hello"` ルートにハンドラを登録し、サービスの開始を行います。

    http.HandleFunc("/hello", hello)
    http.ListenAndServe(":8090", nil)
}

バックグラウンドでサーバーを実行します。

$ go run context-in-http-servers.go &

`/hello` へのクライアント要求をシミュレートし、キャンセルをシグナルするため、起動後にすぐに Ctrl+C を押します。

$ curl localhost:8090/hello
server: hello handler started
^C
server: context canceled
server: hello handler ended

次の例: プロセスをスポーンする