取消正在进行的操作
您可以使用 Go context.Context
管理进行中的操作。Context
是一个标准的 Go 数据值,可以报告它所代表的整体操作是否已被取消并且不再需要。通过在应用程序中跨函数调用和服务传递context.Context
,它们可以提前停止工作并在不再需要处理时返回错误。有关 Context
的更多信息,请参阅Go 并发模式: Context。
例如,您可能想要:
- 结束长时间运行的操作,包括需要很长时间才能完成的数据库操作.
- 从其他地方传播取消请求,例如当客户端关闭连接时.
许多面向 Go 开发人员的 API 都包含带Context
参数的方法,使您更容易在整个应用程序中使用Context
.
超时后取消数据库操作
您可以使用Context
设置超时或截止时间,在此之后将取消操作。要派生(derive)具有超时或截止日期的Context
,请调用context.WithTimeout
或
context.WithDeadline
.
以下超时示例中的代码派生一个Context
并将其传递给 sql.DB
QueryContext
方法.
func QueryWithTimeout(ctx context.Context) {
// 创建具有超时的Context
queryCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
// 使用查询传递超时 Context 。
rows, err := db.QueryContext(queryCtx, "SELECT * FROM album")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
// 处理返回的行.
}
当一个context派生自外部context时,如本示例中queryCtx
派生自ctx
那样,如果取消了外部context,则派生的context也将自动取消。例如,在 HTTP 服务器中,http.Request.Context
方法返回与请求关联的context。如果 HTTP 客户端断开连接或取消 HTTP 请求(可能在 HTTP/2 中),则该context将被取消。如果整个 HTTP 请求被取消或 查询时间超过 5 秒,则将 HTTP 请求的上下文传递给上面的QueryWithTimeout
将导致数据库查询提前停止。
注意: 始终推迟调用当你用具有超时或截止时间创建的新 Context
时返回的 cancel
函数。这将在包含函数退出时释放新Context
所持有的资源。它还取消了queryCtx
,但是当函数返回时,不管什么都不应该再使用 queryCtx
了。