Golang中请求上下文如何取消查询上下文
Golang中请求上下文如何取消查询上下文 你好,
我目前正在使用请求上下文作为数据库查询上下文的“父”上下文。然而,这会导致日志中出现 context canceled 错误。如果我仅使用 Background 上下文作为“父”上下文,则一切正常。这是预期的行为吗?还是我遗漏了什么?
谢谢
当前情况(有问题)
// ctx 是来自处理程序的 `*http.Request.Context`。
func Insert(ctx context.Context) error {
ctx, cancel := context.WithTimeout(ctx, 3 * time.Millisecond)
defer cancel()
qry := `INSERT INTO users (name) VALUES (?)`
res, err := r.database.ExecContext(ctx, qry, "hello")
// ....
}
正常情况
func Insert() error {
ctx, cancel := context.WithTimeout(context.Background(), 3 * time.Millisecond)
defer cancel()
qry := `INSERT INTO users (name) VALUES (?)`
res, err := r.database.ExecContext(ctx, qry, "hello")
// ....
}
更多关于Golang中请求上下文如何取消查询上下文的实战教程也可以访问 https://www.itying.com/category-94-b0.html
2 回复
这是预期的行为。当父上下文被取消时,所有子上下文也必须被取消。你应该调试父上下文,找出它被取消的原因,可能的取消原因可能是超时或网络断开连接。
更多关于Golang中请求上下文如何取消查询上下文的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这是预期的行为。当使用请求上下文作为父上下文时,如果HTTP请求在处理完成前被取消(比如客户端断开连接),数据库查询也会被取消,导致context canceled错误。
示例代码:
// 正确做法:使用请求上下文但处理取消
func Insert(ctx context.Context) error {
// 创建超时上下文,继承请求上下文
queryCtx, cancel := context.WithTimeout(ctx, 3*time.Millisecond)
defer cancel()
qry := `INSERT INTO users (name) VALUES (?)`
// 执行查询
res, err := r.database.ExecContext(queryCtx, qry, "hello")
// 检查是否是上下文取消错误
if err != nil && errors.Is(err, context.Canceled) {
// 请求被取消,这是正常情况
return fmt.Errorf("query canceled due to request cancellation")
}
if err != nil {
return fmt.Errorf("database error: %w", err)
}
// 处理结果
_, err = res.RowsAffected()
if err != nil {
return fmt.Errorf("rows affected error: %w", err)
}
return nil
}
// 如果需要独立于请求的查询,创建分离的上下文
func InsertIndependent() error {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Millisecond)
defer cancel()
qry := `INSERT INTO users (name) VALUES (?)`
res, err := r.database.ExecContext(ctx, qry, "hello")
if err != nil {
return fmt.Errorf("database error: %w", err)
}
_, err = res.RowsAffected()
if err != nil {
return fmt.Errorf("rows affected error: %w", err)
}
return nil
}
使用请求上下文时,查询会随请求取消而终止。使用context.Background()则创建独立上下文,不受请求生命周期影响。两种方式都是有效的,取决于业务需求。

