当前位置: 首页 > news >正文

怎么理解GO中的context

怎么理解GO中的context

一、context本质是上是go的一个接口,该接口的接口方法如下:

type Context interface {
Deadline() (deadline time.Time, ok bool) // 返回到期时间
Done() <-chan struct{} // 只读通道,关闭即代表“该结束了”
Err() error // 为什么结束:取消?超时?
Value(key interface{}) interface{} // 像请求范围的 map,传值用
}

二、具备三个核心能力:

1、取消信号(Done通道关闭)

2、超时控制(Deadline)

3、请求级键值对(Value)

三、五种工厂函数:

函数作用典型场景
context.Background()返回空 Context,永不取消,常做根节点main 函数初始化
context.TODO()和 Background 一样,但语义上表示“以后再加超时/取消”快速原型,占位
context.WithCancel(parent)返回一个可手动取消的子 Context业务逻辑主动取消
context.WithTimeout(parent, timeout)带超时定时器,时间到自动取消数据库、RPC、HTTP 客户端
context.WithDeadline(parent, t)指定绝对时间点到期凌晨 3 点批量任务
context.WithValue(parent, key, val)附加键值对,透传请求数据trace-id、用户 ID

四、最简单的实现方式:

1. 超时场景:数据库查询最多给 500 ms
package mainimport ("context""fmt""time"
)func dbQuery(ctx context.Context) error {// 模拟慢 SQLdone := make(chan struct{})go func() {time.Sleep(600 * time.Millisecond) // 故意超过超时close(done)}()select {case <-ctx.Done(): // 500 ms 后这里会收到信号return ctx.Err() // "context deadline exceeded"case <-done:return nil}
}func main() {ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)defer cancel()if err := dbQuery(ctx); err != nil {fmt.Println("查询失败:", err)return}fmt.Println("查询成功")
}

输出:

查询失败: context deadline exceeded
2. 手动取消:用户中途按 Ctrl+C
package mainimport ("context""fmt""os""os/signal""time"
)func worker(ctx context.Context) {for {select {case <-ctx.Done():fmt.Println("worker 收到取消信号,收尾退出")returndefault:fmt.Println("working...")time.Sleep(300 * time.Millisecond)}}
}func main() {ctx, cancel := context.WithCancel(context.Background())// 把 Ctrl+C 转成取消信号go func() {c := make(chan os.Signal, 1)signal.Notify(c, os.Interrupt)<-ccancel()}()worker(ctx)
}

运行后按 Ctrl+C,worker 会优雅退出。

3. 传值场景:把 trace-id 从 HTTP 中间件传到 DAO 层
type key int
const traceKey key = iotafunc HTTPHandler(w http.ResponseWriter, r *http.Request) {traceID := r.Header.Get("X-Trace-ID")ctx := context.WithValue(r.Context(), traceKey, traceID)Business(ctx)
}func Business(ctx context.Context) {if v := ctx.Value(traceKey); v != nil {fmt.Println("trace-id:", v)}
}

注:任何context的使用都需要调用cancle来避免内存泄漏。调用canle()的瞬间,且ctx.Done()通道被关闭,所有正在阻塞 <-ctx.Done() 的 goroutine 立刻收到“零值”,继续执行收尾逻辑;ctx.Err() 返回非空错误,值固定是 context.Canceled,告诉下游是被人主动取消的;定时器被停止;并向下广播这一状态,比如 WithTimeout 创建的 timerCtx,内部定时器会被 stopTimer() 清理,防止泄漏;接口方法仍然存在,但上下文逻辑生命周期结束,不得再用于派生或传递

http://www.dtcms.com/a/411520.html

相关文章:

  • 国内永久免费建站哈尔滨网站设计有哪些步骤
  • 运动控制教学——5分钟学会样条曲线算法!(三次样条曲线,B样条曲线)
  • HTTP 错误 403.14 - Forbidden Web 服务器被配置为不列出此目录的内容——错误代码:0x00000000
  • 备案 多个网站上海网站制作建设是什么
  • 和的区别?
  • 【LLM LangChain】AgentExecutor 创建带工具的Agent+加入BufferMemory+支持多用户记忆 demos
  • 图书馆网站建设教程专业网站建设咨询
  • Qwen2.5 0.5b转换到iree上支持的文件
  • 做网站和平台多少钱网络营销seo是什么
  • Qt常用控件之QCalendarWidget
  • 做金属小飞机的网站怎么做网络推广网站
  • 利用php做网站教程吃货盒子 wordpress
  • 行政事业单位网站建设直播网站如何做
  • 安装xdebug调试工具(docker容器+vscode编辑器+xdebug)
  • 成都seo培训学校济宁网站建设seo
  • SpringBoot邮件发送的5大隐形地雷与避坑实战指南
  • 撼动GPT-5地位?阿里万亿参数Qwen3-Max模型发布,使用教程来了
  • 三亚市住房和城乡建设厅网站防城港网站设计
  • 西安网址开发 网站制作网站后台管理系统设计
  • HCIP-IoT 真题详解(章节D),嵌入式基础与南向开发 /Part2
  • 如何修改wordpress模板首页宽度做企业网站排名优化要多少钱
  • 守护品牌信誉,激光镭射防伪标签为您筑起安全防线
  • 网站开发课程有哪些龙岩兼职网招聘
  • Unity 虚拟仿真实验中设计模式的使用 ——状态模式(State Pattern)
  • 常见限流策略对比
  • 福建省城乡和建设厅网站陕西网站开发公司
  • 宝山手机网站制作公司那个可以做棋牌网站
  • 360免费建站怎么样排名优化软件点击
  • 如何用vw实现B站手机端底部的《打开app看你想看的视频?》
  • 做自己的网站挣钱境外网站服务器