Skip to content
鼓励作者:欢迎打赏犒劳

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)
}

如有转载或 CV 的请标注本站原文地址