LiSheng's blog LiSheng's blog
首页
笔记
个人简历
随笔集
GitHub (opens new window)
首页
笔记
个人简历
随笔集
GitHub (opens new window)
  • golang

    • 并发编程

      • GMP并发模型
      • 锁相关
      • groutine并发相关
      • go如何实现原子操作
    • 内存管理

    • 数组和切片的区别
    • new和make
    • go defer
    • context
      • channel
      • go map
      • interface
      • 对象系统
      • rune 类型
      • 字符串拼接的几种方式
    • cplus

    • leetcode

    • 存储技术

    • 分布式系统

    • 计算机网络

    • Linux操作系统

    • Redis

    • 其他

    • 笔记
    • golang
    lisheng
    2024-09-10
    目录

    context

    1、context 结构是什么样的? 2、context 使用场景和用途?

    在 Go 语言中,context 是一个标准库提供的结构,用于在多个 Goroutine 之间传递请求的上下文信息。它的主要用途是控制 Goroutine 的生命周期,尤其是在处理超时、取消操作、以及传递请求范围内的元数据时,context 提供了一个简洁且高效的方式。

    # 1. context 结构

    context 实际上是一个接口,主要有四种方法:

    • Deadline() (deadline time.Time, ok bool):返回 context 何时会超时,如果没有设置超时,则 ok 为 false。
    • Done() <-chan struct{}:返回一个 channel,当 context 被取消或超时时,该 channel 会被关闭,通知监听方操作已取消。
    • Err() error:返回 context 结束的原因,如果 Done channel 关闭,Err 返回 context.Canceled 或 context.DeadlineExceeded。
    • Value(key interface{}) interface{}:允许在 context 中存储和检索与 key 相关联的值,用于传递请求范围内的数据。
    func fun1{
        // 创建一个新的上下文,并在其中存储用户ID  
    	ctx := context.WithValue(r.Context(), userIDKey, "12345")  
    	// 将新的上下文传递给下游的处理函数  
    	processRequest(ctx, w)  
    }  
    
    func processRequest(ctx context.Context, w http.ResponseWriter)   
    	// 从上下文中获取用户ID  
    	userID := ctx.Value(userIDKey).(string)  
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    # 2. context 的使用场景

    context 主要用于以下几个场景:

    • Goroutine 的取消:当多个 Goroutine 协作时,context 可以用于在父 Goroutine 取消操作时通知所有子 Goroutine 停止工作。
    • 超时控制:在需要设置超时的场景中,例如 HTTP 请求或数据库查询等操作,context 可以在超时时自动取消操作,避免 Goroutine 长时间阻塞。
    • 传递元数据:context 可以用来传递请求范围内的元数据,比如用户身份信息、授权令牌、跟踪 ID 等。这对于在请求的不同阶段共享数据非常有用。

    # 3. 常用的 context 函数

    Go 提供了几个用于创建和操作 context 的函数:

    • context.Background():返回一个空的上下文,通常作为根 context 使用。
    • context.TODO():在不确定要使用哪个 context 时使用的占位符,后续可以替换为实际的 context。
    • context.WithCancel(parent Context) (ctx Context, cancel CancelFunc):返回一个可取消的 context,调用 cancel 函数可以取消该 context。
    • context.WithDeadline(parent Context, d time.Time) (Context, CancelFunc):返回一个带有截止时间的 context,在指定时间点之后,该 context 会自动取消。
    • context.WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc):返回一个带有超时的 context,超时后自动取消。
    • context.WithValue(parent Context, key, val interface{}) Context:返回一个带有值的 context,可以通过 key 取回 val。

    # 4. context 的示例

    以下是使用 context 控制 Goroutine 取消的示例:

    package main
    
    import (
        "context"
        "fmt"
        "time"
    )
    
    func main() {
        // 创建一个带取消功能的 context
        ctx, cancel := context.WithCancel(context.Background())
        
        // 启动一个 Goroutine
        go func(ctx context.Context) {
            for {
                select {
                case <-ctx.Done():
                    fmt.Println("Goroutine 停止")
                    return
                default:
                    fmt.Println("Goroutine 正在运行")
                    time.Sleep(500 * time.Millisecond)
                }
            }
        }(ctx)
        
        // 主程序等待一段时间后取消 Goroutine
        time.Sleep(2 * time.Second)
        cancel()
        
        // 等待 Goroutine 完成
        time.Sleep(1 * time.Second)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33

    在这个例子中,context.WithCancel 创建了一个带取消功能的 context。当主程序调用 cancel() 时,context.Done() channel 会关闭,Goroutine 检测到此变化后终止运行。

    # 5. context 的最佳实践

    • 不要在函数中传递 nil context:总是使用 context.TODO() 或 context.Background() 作为起点。
    • 及时调用 cancel 函数:确保使用 context.WithCancel 或 context.WithTimeout 时,最终会调用返回的 CancelFunc,以防止资源泄漏。
    • 在请求生命周期中传递 context:在处理 HTTP 请求或 RPC 调用时,将 context 贯穿整个请求生命周期,以便在需要时控制超时和取消。

    context 是 Go 语言并发编程中的一个关键工具,能够有效管理 Goroutine 的生命周期,确保资源的正确释放,并在复杂的并发场景中传递元数据。

    编辑 (opens new window)
    上次更新: 2024/09/13, 11:59:12
    go defer
    channel

    ← go defer channel→

    最近更新
    01
    ceph分布式存储-对象存储(RGW)搭建
    10-27
    02
    ceph分布式存储-集群客户端连接
    10-27
    03
    ceph分布式存储-管理crushmap
    10-27
    更多文章>
    Theme by Vdoing
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式