功能说明
示例为多步骤操作设置一个统一截止时间,并在每一步开始前检查剩余预算。runSteps 先看 ctx.Err(),再通过 ctx.Deadline() 计算 time.Until;如果剩余时间少于该步骤的预计耗时,就立即返回包装了 context.DeadlineExceeded 的错误,而不是启动一个注定超时的等待。
关键代码
if deadline, ok := ctx.Deadline(); ok {
remaining := time.Until(deadline)
if remaining < step.Cost {
return fmt.Errorf(
"step %q needs %s but only %s remains: %w",
step.Name, step.Cost, remaining.Round(time.Millisecond),
context.DeadlineExceeded,
)
}
}
%w 保留错误链,调用方仍可用 errors.Is(err, context.DeadlineExceeded) 判断。
使用注意
time.Until使用真实时钟,剩余时间会随执行不断减少,检查结果只在当下有效。- 预计耗时只是估计值,真正执行仍可能超出预算;实际 I/O 应继续使用带上下文的调用。
- 没有截止时间的上下文会跳过预算检查,只依赖取消信号。
- 计时器在取消分支要调用
Stop(),避免资源泄漏。 - 错误信息包含步骤名和剩余时间,便于定位是哪一个阶段拖慢了整体。
验证方式
示例总预算 80 毫秒,前两步分别 20 与 25 毫秒,第三步需要 60 毫秒,因此应在第三步开始前快速失败并打印剩余时间。把总预算改成 200 毫秒,三步都会完成;改成 10 毫秒可验证第一步就失败。