タイムアウト後のデータベース操作のキャンセル
操作がキャンセルされるタイムアウトまたは期限を設定するために、Context
を使用できます。タイムアウトまたは期限付きのContext
を導出するには、context.WithTimeout
またはcontext.WithDeadline
を呼び出します。
以下のタイムアウト例のコードは、Context
を導出し、それをsql.DB
のQueryContext
メソッドに渡します。
func QueryWithTimeout(ctx context.Context) {
// Create a Context with a timeout.
queryCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
// Pass the timeout Context with a query.
rows, err := db.QueryContext(queryCtx, "SELECT * FROM album")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
// Handle returned rows.
}
この例では、queryCtx
がctx
から導出されるように、外部コンテキストから導出された場合、外部コンテキストがキャンセルされると、導出されたコンテキストも自動的にキャンセルされます。たとえば、HTTPサーバーでは、http.Request.Context
メソッドはリクエストに関連付けられたコンテキストを返します。そのコンテキストは、HTTPクライアントが切断するか、HTTPリクエストをキャンセルすると(HTTP/2で可能)、キャンセルされます。上記のQueryWithTimeout
にHTTPリクエストのコンテキストを渡すと、全体のHTTPリクエストがキャンセルされた場合、またはクエリが5秒以上かかった場合に、データベースクエリが早期に停止します。
注意: タイムアウトまたは期限付きの新しいContext
を作成するときに返されるcancel
関数の呼び出しは常に遅延させてください。これにより、含まれる関数が終了するときに新しいContext
が保持しているリソースが解放されます。また、queryCtx
もキャンセルされますが、関数が戻る時点でqueryCtx
を使用しているものは何もないはずです。