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 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了