取消正在进行的操作
您可以使用 Go context.Context
管理正在进行的操作。Context
是一个标准的 Go 数据值,它可以报告其所代表的整体操作是否已取消且不再需要。通过在应用程序的函数调用和服务中传递 context.Context
,这些调用和服务可以在不再需要其处理时尽早停止工作并返回错误。有关 Context
的更多信息,请参阅 Go 并发模式:Context。
例如,您可能希望
- 结束长时间运行的操作,包括需要花费很长时间才能完成的数据库操作。
- 传播来自其他地方的取消请求,例如当客户端关闭连接时。
许多面向 Go 开发者的 API 包含采用 `Context` 参数的方法,让你能够更轻松地在整个应用程序中使用 `Context`。
在超时后取消数据库操作
你可以使用 `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 中可能发生),则该上下文会被取消。将 HTTP 请求的上下文传递到上面的 `QueryWithTimeout` 将导致数据库查询在以下任一情况下提前停止:HTTP 请求被取消或查询花费的时间超过五秒。
注意:始终推迟对创建具有超时或截止时间的 `Context` 时返回的 `cancel` 函数的调用。这会在包含函数退出时释放由新 `Context` 持有的资源。它还会取消 `queryCtx`,但当函数返回时,不应该再有内容使用 `queryCtx`。