GoLang教程——Context上下文实战

在 Go 的并发编程中,context(上下文)包是绝对的核心。无论是处理 HTTP 请求、RPC 调用,还是数据库查询,Context 都扮演着控制 Goroutine 生命周期的角色。 简而言之,Context 主要解决三个问题: 取消信号:通知子 Goroutine 停止工作,释放资源。 超时控制:规定任务必须在多长时间内完成,否则强制取消。 数据传递:在调用链中传递请求范围内的元数据(如 UserID, TraceID)。 1. 为什么需要 Context? 假设你启动了一个 Goroutine 去查询数据库,如果用户突然关闭了浏览器,或者请求处理太慢超时了,你希望这個后台查询任务能立即停止,而不是继续浪费数据库资源。这就是 Context 的用武之地。 Go 的设计原则:谁启动了 Goroutine,谁就有责任(通过 Context)管理它的退出。 2. 超时控制 (WithTimeout) 这是 Context 最常用的场景。 1package main 2 3import ( 4 "context" 5 "fmt" 6 "time" 7) 8 9func main() { 10 // 1. 创建一个带超时的 Context 11 // 规定任务必须在 2 秒内完成,否则 ctx 会收到取消信号 12 ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) 13 // 关键:函数结束时必须调用 cancel,防止内存泄漏 14 defer cancel() 15 16 fmt.Println("Start working...") 17 18 // 2. 将 ctx 传递给耗时任务 19 doSlowWork(ctx) 20} 21 22func doSlowWork(ctx context.Context) { 23 // 模拟一个需要 3 秒才能完成的任务 24 // Select 会等待 done 信号或者 work 完成,以此来实现超时抢占 25 select { 26 case <-time.After(3 * time.Second): // 模拟业务逻辑 27 fmt.Println("Work done successfully!") 28 case <-ctx.Done(): // 监听 Context 的取消信号 29 // 如果超时了,ctx.Err() 会返回 DeadlineExceeded 30 fmt.Println("Work cancelled:", ctx.Err()) 31 } 32} 运行结果: 由于任务耗时 3秒,但 Context 限制 2秒,所以输出: Work cancelled: context deadline exceeded ...

2025-03-02 · 2 min · 359 words · Hank