Context とは
Package context defines the Context type, which carries deadlines, cancellation signals, and other request-scoped values across API boundaries and between processes.
簡単に訳すと、こんな感じ
処理の締め切り・キャンセル信号・API 境界やプロセス間を横断する必要のある
リクエストスコープな値を伝達させることができます。
context の定義は以下の通りです
type Context interface {
// Deadline 期限を返す
Deadline() (deadline time.Time, ok bool)
// Done チャネルを返す。チャネルはキャンセル・期限切れの場合は閉じる
Done() <-chan struct{}
// Err Doneが閉じた理由を返す
Err() error
// Value Contextに格納した値を返す
Value(key interface{}) interface{}
}
context.Backgroud() context の初期化
0 の状態からコンテキストを生成するにはcontext.Backgroud()
を用いる
これは、「キャンセルされない」「deadline を持たない」「共有する値を持たない」状態
context.Withcancel() キャンセルを行う
上記で初期化した値にcontext.WithCancel()
を渡すことで、
「Done
からキャンセル有無が判断できる context」と「戻り値のコンテキストをキャンセルするための関数」を取得できます
func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
例えば、以下のような形で渡すことで動作する
ctx, cancel := context.WithCancel(context.Backgroud())
// cancel() ctx.Done()で得られるチャネルがcloseされる
cancel()
context.WithDeadine() 自動タイムアウトの行う
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc)
context.WithDeadline()
は、引数で渡された親 context の設定を引き継いだ上で
Done メソッドチャネルが第二引数で指定した時刻に自動で close される新たな context になる
タイムアウト前にキャンセルを行うたい場合は、cancel()
を呼び出すことでも close できる
// ctxはtime.Now().Add(time.Second)に自動キャンセルされる
ctx, cancel := context.WithDeadline(context.Backgroud(), time.Now().Add(time.Second))
// 明示的にcancelさせることもできる
cancel()
context.WithDeadline()
を使うことで時刻タイムアウトをできましたが、
context.WithTimeout()
を使うことで時間でタイムアウトさせることも可能です
タイムアウトの有無判定
// ~~ 略~~
case result, ok := <-gen:
if ok {
fmt.Println(result)
} else{
fmt.Println(result)
break
}
これにより、gen チャネルの close 処理が行われるようになる
そのため、タイムアウトかどうかを判定するにはgenチャネルからの受信が、
チャネルcloseによるものか否か
を見るだけで判定できる
Deadline メソッドによる、時刻確認、タイムアウトの有無
type Context interface {
Deadline() (deadline time.Time, ok bool)
}
第二引数の bool を確認することで、その context がタイムアウトに設定されるか判定できる
設定されている場合は、第一引数にタイムアウト時刻が格納される
Err キャンセルなのかタイムアウトなのか判定する
type Context interface {
Err() error
}
context の Err メソッドは、context がキャンセルされた時は nil
明示的にキャンセルされた場合は、Canceled エラー
タイムアウトしていた場合は、DeadlineExceeded エラー
Value 値の付加
func WithValue(parent Context, key, val interface{}) Context
WithValue を使うことで、context に値を加えることができます。
引数 key は key が、val には value を内部に持ちます。
// ctx内部にkeyが"userID", valueが2入る
ctx = context.WithValue(parentCtx, "userID", 2)