← 中文资源

简体中文版本

在多个步骤间共享 Context 截止时间

为多步骤操作设置统一超时,每次执行前检查剩余预算,发现时间不够时立即返回包装后的超时错误,而不是白等。

阅读英文原文

功能说明

示例为多步骤操作设置一个统一截止时间,并在每一步开始前检查剩余预算。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 毫秒可验证第一步就失败。