随笔 - 14  文章 - 0  评论 - 1  阅读 - 13793

go的context包基本使用

Golang 使用树形派生的方式构造 Context,通过在不同过程 [1] 中传递 deadline 和 cancel 信号,来管理处理某个任务所涉及到的一组 goroutine 的生命周期,防止 goroutine 泄露。并且可以通过附加在 Context 上的 Value 来传递/共享一些跨越整个请求间的数据。

Context 最常用来追踪 RPC/HTTP 等耗时的、跨进程的 IO 请求的生命周期,从而让外层调用者可以主动地或者自动地取消该请求,进而告诉子过程回收用到的所有 goroutine 和相关资源。

context是线程安全的。

 

基本使用代码示例:

复制代码
 1 package main
 2 
 3 import (
 4     "context"
 5     "fmt"
 6     "time"
 7 )
 8 
 9 // 测试使用context, WithTimeout,WithCancel,WithDeadline,需要在协程内部来检测取消信号,然后退出
10 
11 func main() {
12     // 给一个协程设置超时时间, 5秒后协程自动调用cancel方法
13     ctx, cancelFunc := context.WithTimeout(context.Background(), 5 * time.Second)
14 
15     // 给一个协程设置取消信号,需要取消时,直接执行取消方法
16     ctx2, cancel := context.WithCancel(context.Background())
17     // 给一个协程设置过期时间, 3秒后自动调用cancel方法
18     ctx3, cancelFunc2 := context.WithDeadline(context.Background(), time.Now().Add(3*time.Second))
19     // 设置value
20     ctx4 := context.WithValue(context.Background(), "traceId", "abcdefdg")
21 
22     go testTimeOut(ctx, "监控1")
23     go testTimeOut(ctx, "监控2")
24     go testCancel(ctx2)
25     go testDeadLine(ctx3, "dead 监控1")
26     go testDeadLine(ctx3, "dead 监控2")
27 
28     go testValue(ctx4)
29 
30     time.Sleep(time.Second * 2)
31     // 调用取消
32     cancel()
33 
34     time.Sleep(10000 * time.Second)
35     cancelFunc()  // 最终调用超时
36     cancelFunc2() // 最终调用过期时间
37 }
38 
39 func testTimeOut(ctx context.Context, name string) {
40     for {
41         select {
42         case <-ctx.Done():
43             fmt.Println(name, "执行超时了")
44             return
45         default:
46             fmt.Println(name, "goroutine监控中,time=", time.Now().Unix())
47             time.Sleep(1 * time.Second)
48         }
49     }
50 
51 }
52 
53 func testCancel(ctx context.Context) {
54     // 检测取消信号
55     for {
56         select {
57           case <-ctx.Done():
58               fmt.Println("取消了")
59               return
60         default:
61             fmt.Println("goroutine执行中,time=", time.Now().Unix())
62             time.Sleep(1 * time.Second)
63         }
64     }
65 }
66 
67 
68 func testDeadLine(ctx context.Context, name string) {
69     for {
70         select {
71         case <-ctx.Done():
72             fmt.Println(name, "收到信号,监控退出,time=", time.Now().Unix())
73             return
74         default:
75             fmt.Println(name, "goroutine监控中,time=", time.Now().Unix())
76             time.Sleep(1 * time.Second)
77         }
78     }
79 }
80 
81 // 测试调用value
82 func testValue(ctx context.Context) {
83     traceId, ok := ctx.Value("traceId").(string)
84     if ok {
85         fmt.Printf("process over. trace_id=%s\n", traceId)
86     } else {
87         fmt.Printf("process over. no trace_id\n")
88     }
89     return
90 }
复制代码

 

posted on   啊哈好223  阅读(173)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5

点击右上角即可分享
微信分享提示