【一分钟快学】Go 语言中的 Context:管理取消信号、超时和值传递

想象一下,你正在一家快餐店等待你的订单。你的订单是由多个步骤组成的:首先是下单,然后是制作食物,最后是打包给你。在这个过程中,如果你决定取消订单,你希望快餐店立刻停止制作和打包,以节省时间和资源。这个"取消订单"的动作,就是 context 所做的事情。

context 是 Go 语言在 1.7 版本引入的一个标准库包,主要用来处理超时、取消操作和传递请求相关的值。它是一个为了让程序更加健壮、更容易管理而设计的功能。

context 做什么的?

  1. 取消信号 :它可以向所有使用同一个 context 的 goroutine 发送取消信号。这在你想要停止正在执行的操作时非常有用,比如说当用户取消了请求,或者操作已经超时了。
  2. 超时控制context 可以设定一个超时时间,一旦过了这个时间,就会自动发送取消信号。这对于控制那些可能会花费很长时间才能完成的操作特别有用。
  3. 值传递context 还可以用来传递请求范围内的数据,比如用户的身份信息、授权token等,这样在整个请求链中的任何一个环节都可以访问到这些信息。

怎么用?

使用 context 的典型模式是通过 context.Background()context.TODO() 创建一个根 context,然后通过 context.WithCancel()context.WithDeadline()context.WithTimeout()context.WithValue() 来派生出子 context

取消信号

go 复制代码
import (
    "context"
    "fmt"
    "time"
)

func main() {
    // 创建一个根context
    ctx, cancel := context.WithCancel(context.Background())
    
    // 在一个goroutine中使用这个context
    go func() {
        time.Sleep(2 * time.Second)
        // 2秒后发送取消信号
        cancel()
    }()
    
    // 等待取消信号
    <-ctx.Done()
    fmt.Println("Received cancel signal, shutting down...")
}

超时控制

go 复制代码
package main

import (
    "context"
    "fmt"
    "time"
)

func operation(ctx context.Context) {
    for {
        select {
        case <-time.After(3500 * time.Millisecond): // 模拟耗时的操作
            fmt.Println("operation finished")
        case <-ctx.Done():
            fmt.Println("operation cancelled")
            return
        }
    }
}

func main() {
    // 创建一个将在1秒后超时的context
    ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
    defer cancel() // 不要忘记调用cancel

    go operation(ctx)

    // 等待足够长的时间,以观察操作是否会因为超时而取消
    time.Sleep(2 * time.Second)
}

值传递

go 复制代码
package main

import (
    "context"
    "fmt"
)

func process(ctx context.Context) {
    // 从context中提取值
    if v := ctx.Value("key"); v != nil {
        fmt.Println("found value:", v)
        return
    }
    fmt.Println("value not found")
}

func main() {
    ctx := context.Background()
    // 使用context.WithValue来传递值
    ctx = context.WithValue(ctx, "key", "this is a value")

    process(ctx)
}
相关推荐
天远云服16 小时前
Go语言高并发实战:集成天远手机号码归属地核验API打造高性能风控中台
大数据·开发语言·后端·golang
钱多多_qdd16 小时前
springboot注解(二)
java·spring boot·后端
神奇小汤圆16 小时前
MyBatis批量插入从5分钟优化到3秒,我做了这3件事
后端
上去我就QWER16 小时前
什么是反向代理?
后端·nginx
Charlo16 小时前
手把手配置 Ralph -- 火爆 X 的全自动 AI 编程工具
前端·后端·github
CRUD酱17 小时前
后端使用POI解析.xlsx文件(附源码)
java·后端
2501_9418024817 小时前
从缓存更新到数据一致性的互联网工程语法实践与多语言探索
java·后端·spring
钱多多_qdd17 小时前
springboot注解(五)
java·spring boot·后端
IT_陈寒18 小时前
React 18实战:这5个新特性让我的开发效率提升了40%
前端·人工智能·后端
a努力。18 小时前
京东Java面试被问:双亲委派模型被破坏的场景和原理
java·开发语言·后端·python·面试·linq