Go中重试机制核心是for循环+错误判断+延迟等待;基础实现为固定次数重试,每次失败且未达上限则继续,否则返回最终错误。

在 Go 中实现重试机制,核心是用 for 循环 + 错误判断 + 延迟等待 构建可控的重试逻辑,避免无限重试或过快失败。
基础重试:固定次数 + 简单错误检查
最常用的方式是设定最大重试次数,每次执行操作后检查是否出错。若失败且未达上限,则继续循环;否则返回最终错误。
- 用
for i := 0; i 控制尝试次数 - 每次调用目标函数(如 HTTP 请求、数据库查询)后,立即检查
err != nil - 若出错且不是最后一次尝试,用
time.Sleep()暂停后再重试 - 成功则直接
return result, nil;循环结束仍未成功,返回最后一次错误
带退避策略的重试:避免雪崩和资源争抢
简单固定延迟容易造成重试洪峰,尤其在服务刚恢复时。引入指数退避(exponential backoff)更健壮:
- 每次重试延迟 = 初始延迟 × (2 ^ 当前重试次数),例如 100ms → 200ms → 400ms
- 可加入随机抖动(jitter),防止大量请求同步重试:延迟 × (0.5 ~ 1.5)
- 用
time.Sleep(time.Duration(baseDelay) * time.Millisecond)实现暂停
可取消与上下文支持:适配真实业务场景
生产环境常需响应取消信号或超时控制,应基于 context.Context 实现:
立即学习“go语言免费学习笔记(深入)”;
- 函数接收
ctx context.Context参数,并在每次重试前检查ctx.Err() != nil - 使用
select在操作和上下文完成之间做选择,避免阻塞等待 - 推荐组合
context.WithTimeout或context.WithCancel,让重试本身可中断
封装成可复用函数:提升代码一致性
把重试逻辑抽成通用函数,减少重复代码,也便于统一配置(如默认重试次数、退避参数):
- 定义函数签名如:
func DoWithRetry(ctx context.Context, fn func() error, opts ...RetryOption) error - 通过选项模式(functional options)传入最大重试次数、初始延迟、是否启用 jitter 等
- 内部统一处理循环、错误判定、延迟计算和上下文检查
- 调用时只需写业务逻辑闭包,例如:
DoWithRetry(ctx, callExternalAPI, WithMaxRetries(3), WithBackoff(100))
不复杂但容易忽略的是错误分类——有些错误(如 400 Bad Request)不该重试,而 408/500/网络超时才适合。实际使用中建议先判断错误类型再决定是否进入重试分支。










