Go语言Context包:并发控制与请求取消

Go语言Context包:并发控制与请求取消

引言

Go语言的context包是并发编程中的重要工具,用于管理goroutine生命周期和传递请求范围数据。本文将讲解context的使用场景,并通过HTTP服务器示例展示其在并发控制中的应用。

Context的核心功能

context包提供以下功能:

  • 取消信号:通知goroutine停止执行。
  • 超时控制:设置任务执行时间限制。
  • 值传递:在goroutine间传递请求相关数据。

示例:HTTP服务器超时控制

以下是一个使用context的HTTP服务器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main

import (
"context"
"fmt"
"net/http"
"time"
)

func handler(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
defer cancel()

select {
case <-time.After(3 * time.Second):
fmt.Fprintln(w, "任务完成")
case <-ctx.Done():
fmt.Fprintln(w, "任务超时")
}
}

func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}

解析context.WithTimeout设置5秒超时,ctx.Done()通道在超时或请求取消时关闭。

使用场景

1. 数据库查询

控制数据库查询超时:

1
2
3
4
5
6
7
8
9
10
11
func queryDB(ctx context.Context, query string) (string, error) {
ctx, cancel := context.WithTimeout(ctx, 2*time.Second)
defer cancel()
// 模拟数据库查询
select {
case <-time.After(1 * time.Second):
return "查询结果", nil
case <-ctx.Done():
return "", ctx.Err()
}
}

2. 微服务通信

在gRPC调用中使用context传递元数据:

1
ctx := context.WithValue(context.Background(), "user-id", "123")

注意事项

  • 避免滥用Context值:仅传递请求范围数据,避免用作全局变量。
  • 正确取消:总是调用cancel()释放资源。
  • 嵌套Context:合理使用WithTimeoutWithCancel管理层级关系。

总结

context包是Go并发编程的利器,简化了超时控制和请求取消的实现。通过合理使用context,可以提升服务的健壮性和响应性。希望本文的示例能为你的Go开发提供实用指导!