取消正在进行的操作

您可以使用 Go context.Context管理进行中的操作。Context是一个标准的 Go 数据值,可以报告它所代表的整体操作是否已被取消并且不再需要。通过在应用程序中跨函数调用和服务传递context.Context,它们可以提前停止工作并在不再需要处理时返回错误。有关 Context的更多信息,请参阅Go 并发模式: Context

例如,您可能想要:

许多面向 Go 开发人员的 API 都包含带Context参数的方法,使您更容易在整个应用程序中使用Context.

超时后取消数据库操作

您可以使用Context设置超时或截止时间,在此之后将取消操作。要派生(derive)具有超时或截止日期的Context,请调用context.WithTimeoutcontext.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 了。