Go语言中的Context:请求生命周期管理

发布时间:2026/6/19 0:00:03

Go语言中的Context:请求生命周期管理 Go语言中的Context请求生命周期管理1. Context的基本概念Context是Go语言中用于管理请求生命周期的重要工具它提供了超时控制、取消信号和键值存储等功能。Context是Go语言并发编程和网络编程的核心组件广泛应用于HTTP请求、数据库操作和RPC调用等场景。本文将详细介绍Go语言中的Context从基础用法到高级技巧帮助开发者掌握Context的各种功能。2. Context的基础用法2.1 创建Contextpackage main import ( context fmt ) func main() { // 创建根Context ctx : context.Background() fmt.Println(Background context:, ctx) // 创建TODO Context ctx2 : context.TODO() fmt.Println(TODO context:, ctx2) }2.2 带超时的Contextpackage main import ( context fmt time ) func main() { // 创建带超时的Context ctx, cancel : context.WithTimeout(context.Background(), 2*time.Second) defer cancel() select { case -time.After(3 * time.Second): fmt.Println(Operation completed) case -ctx.Done(): fmt.Println(Context cancelled:, ctx.Err()) } }2.3 带取消的Contextpackage main import ( context fmt time ) func main() { // 创建可取消的Context ctx, cancel : context.WithCancel(context.Background()) // 启动协程 go func() { time.Sleep(2 * time.Second) cancel() // 取消Context }() select { case -time.After(3 * time.Second): fmt.Println(Operation completed) case -ctx.Done(): fmt.Println(Context cancelled:, ctx.Err()) } }3. Context的高级用法3.1 Context的链式调用package main import ( context fmt time ) func main() { // 创建根Context rootCtx : context.Background() // 添加超时 ctx1, cancel1 : context.WithTimeout(rootCtx, 5*time.Second) defer cancel1() // 添加取消 ctx2, cancel2 : context.WithCancel(ctx1) defer cancel2() // 添加值 ctx3 : context.WithValue(ctx2, key, value) fmt.Println(Context chain created) fmt.Println(Value:, ctx3.Value(key)) }3.2 Context值的传递package main import ( context fmt ) type contextKey string const ( UserIDKey contextKey user_id TraceIDKey contextKey trace_id ) func main() { // 创建带值的Context ctx : context.WithValue(context.Background(), UserIDKey, 12345) ctx context.WithValue(ctx, TraceIDKey, abc-def-ghi) // 获取值 if userID, ok : ctx.Value(UserIDKey).(string); ok { fmt.Println(User ID:, userID) } if traceID, ok : ctx.Value(TraceIDKey).(string); ok { fmt.Println(Trace ID:, traceID) } }4. Context的实战应用4.1 HTTP请求处理package main import ( context fmt net/http time ) func handler(w http.ResponseWriter, r *http.Request) { // 从请求中获取Context ctx : r.Context() // 设置超时 ctx, cancel : context.WithTimeout(ctx, 5*time.Second) defer cancel() // 模拟处理 select { case -time.After(3 * time.Second): fmt.Fprintln(w, Request processed) case -ctx.Done(): http.Error(w, Request timeout, http.StatusGatewayTimeout) } } func main() { http.HandleFunc(/, handler) http.ListenAndServe(:8080, nil) }4.2 数据库操作package main import ( context database/sql fmt time ) func queryDatabase(ctx context.Context, db *sql.DB) error { // 设置查询超时 ctx, cancel : context.WithTimeout(ctx, 3*time.Second) defer cancel() var result string err : db.QueryRowContext(ctx, SELECT name FROM users WHERE id ?, 1).Scan(result) if err ! nil { return err } fmt.Println(Result:, result) return nil }4.3 并发控制package main import ( context fmt sync time ) func worker(ctx context.Context, id int, wg *sync.WaitGroup) { defer wg.Done() for { select { case -ctx.Done(): fmt.Printf(Worker %d stopped\n, id) return default: fmt.Printf(Worker %d working\n, id) time.Sleep(500 * time.Millisecond) } } } func main() { ctx, cancel : context.WithTimeout(context.Background(), 3*time.Second) defer cancel() var wg sync.WaitGroup // 启动多个工作协程 for i : 0; i 3; i { wg.Add(1) go worker(ctx, i, wg) } wg.Wait() fmt.Println(All workers stopped) }5. Context的最佳实践5.1 Context的传播将Context作为函数的第一个参数传递不要存储Context在结构体中使用WithValue时键应该是自定义类型5.2 Context的生命周期及时调用cancel函数避免资源泄漏不要复用已经取消的Context合理设置超时时间5.3 Context的值使用只存储请求相关的元数据不要存储业务数据使用自定义类型作为键6. 总结Context是Go语言中管理请求生命周期的重要工具通过合理使用Context我们可以实现超时控制、取消信号和元数据传递等功能。在使用Context时应该注意以下几点将Context作为函数的第一个参数传递及时调用cancel函数避免资源泄漏合理设置超时时间只使用Context存储请求相关的元数据利用Context实现优雅的取消和超时控制通过合理使用Context我们可以构建更加健壮、可靠的Go应用程序。

相关新闻