外观
context、超时与取消
- 状态:未准备
- 适用方向:Go 全栈 / Go 后端
- 最近复习:待填写
- 下次复习:待安排
一句话回答
context 传播截止时间、取消信号和请求范围值;取消是协作通知,不会强杀 goroutine,也不代表下游业务已回滚。
原理解释
父取消影响派生子 context,子取消不影响父,也不能延长父截止时间。WithCancel、WithTimeout 返回的 cancel 应在所有路径调用。
go
ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, upstream, nil)
if err != nil { return err }
resp, err := client.Do(req)
if err != nil { return err }
defer resp.Body.Close()
// 位于返回 error 的函数中;还需处理响应状态码和内容。Done 监听退出,Err 区分 Canceled 与 DeadlineExceeded。context 作为首参数显式传递,不传 nil;Value 存请求范围元数据,不替代业务参数和配置。
场景与边界
HTTP、数据库、模型调用共享合理预算,下游超时要给清理留余量。客户端超时时服务端可能已提交,仍需业务幂等或状态查询。
后台任务需要独立生命周期、容量与退出机制,改用 Background 不等于可靠。流式响应应按长连接特点设计超时。
项目中的应用
结合 EinoTalk Agent与 SimulSpeak 停止流程,检查取消是否传至 provider、晚到结果是否仍更新状态。
常见追问
- cancel 会等待退出吗? 不会,需额外完成通知或 WaitGroup。
- select 能取消阻塞函数吗? 函数不支持取消就仍可能运行;另起 goroutine 也可能留下泄漏。
- 能并发共享吗? context API 可以,其中保存的可变对象仍需自行同步。