GoLang教程——Context上下文实战

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

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

(译)Go并发模式——Context

原文地址: https://go.dev/blog/context 作者:Sameer Ajmani 时间:29 July 2014 1. 简介 [1] 在 Go 服务器中,每个传入的请求都在其自己的 goroutine 中处理。请求处理程序通常会启动额外的 goroutine 来访问数据库和 RPC 服务等后端。处理请求的一组 goroutine 通常需要访问特定于请求的值,例如最终用户的身份、授权令牌和请求的截止日期。当请求被取消或超时时,所有处理该请求的 goroutines 都应该快速退出,以便系统可以回收它们正在使用的任何资源。 在 Google,我们开发了一个 context 包,可以轻松地将请求范围的值、取消信号和截止日期等跨 API 边界传递给正在处理请求的所有 goroutine。 该软件包 作为context公开可用 。本文介绍了如何使用该包并提供了一个完整的工作示例。 2. Context context 包的核心是 Context 类型: type Context interface { (1) Done() <-chan struct{} (2) Err() error (3) Deadline() (deadline time.Time, ok bool) (4) Value(key interface{}) interface{} (5) } 1 Context 携带截止日期、取消信号和请求范围的跨越 API 边界的值,多个 goroutine 同时使用它的方法是安全的。 2 Done 返回一个在此 Context 取消或超时时的通道(chan) 3 Err 错误信息说明 context 为什么被取消, 在 Done 返回的 chan 被关闭之后获取 4 Deadline 返回 Context 被取消的时间 5 Value 返回参数 key 关联的值,没有则返回 nil ...

2022-07-19 · 5 min · 887 words · Hank