ZBLOG

package context作用

在 Go 语言中,context 包(package context)是用于跨 goroutine 传递请求作用域数据、控制并发生命周期的核心工具。它主要用于解决以下问题:


1. 核心作用

功能 说明
取消传播 通过 ctx.Done() 通知多个 goroutine 退出(如超时、手动取消)。
超时控制 通过 WithTimeout/WithDeadline 设置截止时间,自动触发取消。
值传递 通过 WithValue 安全传递请求范围内的数据(如 traceID、认证信息)。
父子级联取消 父 context 被取消时,所有派生出的子 context 会自动触发取消。

2. Context 接口方法

type Context interface {
    Deadline() (deadline time.Time, ok bool) //返回设置的截止时间
    Done() <-chan struct{}                   //返回一个 channel,用于监听取消信号
    Err() error                              //返回取消原因(超时/主动取消)
    Value(key any) any                       //获取关联的值
}

3. 常用创建函数

(1) Background / TODO

ctx := context.Background() //根 context,通常作为顶层 context
ctx = context.TODO()       //暂不确定用途时的占位符(语义化)

(2) WithCancel

ctx, cancel := context.WithCancel(parentCtx)
defer cancel() //手动调用 cancel() 触发取消

(3) WithTimeout / WithDeadline

// timeout: "从现在开始最多允许运行多久"
ctx, cancel := context.WithTimeout(parentCtx, time.Second * 5)
defer cancel()

// deadline: "必须在某个具体时间点前完成"
deadline := time.Now().Add(time.Second * 5)
ctx, cancel := context.WithDeadline(parentCtx, deadline)

(4) WithValue

type key string
ctx := context.WithValue(parentCtx, key("userID"), "123")
userID := ctx.Value(key("userID")).(string) //需类型断言

⚠️ 注意

  • Key应使用自定义类型(避免字符串冲突)。
  • Value应该是线程安全的不可变数据。

4. 典型应用场景

(1) HTTP Server 请求控制

func handler(w http.ResponseWriter, r *http.Request) {
    ctx := r.Context()
    select {
    case <-time.After(2 * time.Second):
        fmt.Fprint(w, "Hello")
    case <-ctx.Done(): //客户端断开连接时触发
        err := ctx.Err()
        log.Printf("Request canceled: %v", err)
    }
}

(2) RPC/数据库查询超时

ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
defer cancel()

result, err := db.QueryContext(ctx, "SELECT...") 
if errors.Is(err, context.DeadlineExceeded) {
    log.Println("Query timeout!")
}

(3) Goroutine 树的生命周期管理

func worker(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            return //父级取消时自动退出
        default:
            fmt.Println("Working...")
            time.Sleep(time.Second)
        }
    }
}

func main() {
    parentCtx, cancel := context.WithCancel(context.Background())
    go worker(parentCtx)

    time.Sleep(5 * time.Second)
    cancel() //通知所有子 goroutine退出
}

5. ⚠️注意事项

  1. 不要滥用 WithValue:仅传递必要的请求范围数据(如 traceID),而非函数参数。
  2. 及时释放资源:调用 cancel() 防止 goroutine泄漏(即使提前结束)。
  3. Err()检查必要性
    
    if ctx.Err() == context.Canceled { ... }
    
  4. 性能影响:频繁创建嵌套的context可能增加微小开销。

6. vs Channel + Select

Context Channel + Select
适用场景 树状goroutine生命周期管理 简单的一对一通信
灵活性 内置超时/值传递 需手动实现
标准库支持 广泛集成于HTTP/gRPC/database等 原生语法

总结:
Context是Go并发编程中管理复杂任务链路的首选工具,尤其在微服务、网络请求等场景下不可或缺。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=24046

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?