取消正在进行的操作

Canceling in-progress operations - 取消正在进行的操作

原文:https://go.dev/doc/database/cancel-operations

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

例如,您可能想:

  • 结束长期运行的操作,包括需要太长时间才能完成的数据库操作。
  • 传播来自其他地方的取消请求,例如当客户端关闭连接时。

​ 许多为Go开发者提供的API都包含接受Context实参的方法,这使得在整个应用程序中更容易使用Context

在超时后取消数据库操作

​ 您可以使用 Context 来设置一个超时或最后期限,超时后的操作将被取消。要派生一个带有超时或最后期限的Context,请调用context.WithTimeoutcontext.WithDeadline

​ 下面的超时例子中的代码派生了一个Context,并将其传递给sql.DB QueryContext方法。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
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请求被取消或者查询时间超过5秒的话。

注意

​ 当您创建一个有超时或截止日期的新Context时,(一定记得)始终推迟对cancel函数的调用。这将在外层函数退出时释放新Context所持有的资源。它也会取消queryCtx,但是当函数返回时,就不会再有任何东西使用 queryCtx 了。