
go重试工具类
这个需求很常见,其实就是为了不阻塞接口,我们一般会走异步处理,然后加上重试机制。支持传参
工具类
go
package retry_util
import (
"context"
"fmt"
"log"
"time"
)
// Retry 函数
// fn: 需要执行的函数,返回值为 (success bool, err error)
// maxRetries: 最大重试次数(包含第一次执行)
// 返回值:
// - success: 是否最终成功
// - err: 执行过程中最后一次返回的错误(如果有的话)
func Retry(ctx context.Context, fn func() (bool, error), maxRetries int) (bool, error) {
if maxRetries <= 0 {
return false, fmt.Errorf("重试次数必须大于 0")
}
var lastErr error
for i := 0; i < maxRetries; i++ {
// 如果是第2次及以后的尝试,可以加点日志或延时
if i > 0 {
// 可选:增加指数退避或固定延迟
time.Sleep(time.Millisecond * 100 * time.Duration(i)) // 简单的线性退避
log.Printf("第 %d 次重试...", i+1)
}
success, err := fn()
if err != nil {
lastErr = err // 记录错误,便于后续返回
}
if success {
log.Printf("✅ 成功!在第 %d 次尝试后完成。", i+1)
return true, nil
}
// 如果失败且还有重试机会,继续循环
if i < maxRetries-1 {
continue
}
}
// 所有尝试都失败了
return false, fmt.Errorf("重试 %d 次后仍然失败: %w", maxRetries, lastErr)
}测试
go
package main
import (
"context"
"demo/utils/retry_util"
"math/rand"
"time"
)
func TranslationTextHandleRetry(ctx context.Context, id string, text string) {
count := 1
fakeAPICall := func(id string, text string) (bool, error) {
// 业务逻辑 模拟重试
if count > 2 {
return true, nil
}
count++
time.Sleep(time.Duration(rand.Intn(1000)) * time.Millisecond)
return false, nil
}
go func() {
_, err := retry_util.Retry(ctx, func() (bool, error) {
return fakeAPICall(id, text)
}, 3)
if err != nil {
return
}
}()
}
func main() {
TranslationTextHandleRetry(context.Background(), "123", "xxx")
time.Sleep(time.Duration(rand.Intn(10000)) * time.Millisecond)
}
