likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 40

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

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

context 官方文档:pkg.go.dev/context

context 做什么的?

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

怎么用?

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

取消信号

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...")
}

超时控制

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)
}

值传递

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)
}
转载自:https://juejin.cn/post/7338601378486370356
评论
请登录