实现思路:
- 重试配置定义最大重试次数和固定重试间隔;
- 使用接口优雅传递可选重试配置参数;
- 重试的模板方法必须返回错误,且只有一个返回值;
- 如果需要使用被重试方法的返回值,使用匿名方法包一层真实方法并在匿名方法中赋值真实方法的返回值;
- 真实方法返回error时会进行重试;
重试配置
// 重试配置结构
type Config struct {
MaxRetryTime int // 最大重试次数
Interval int // 固定重试间隔
}
// 构造默认重试配置
func NewDefaultConfig() *Config {
return &Config {
MaxRetryTime : DefaultMaxRetryTime,
Interval : DefaultInterval,
}
}
// 默认重试配置常量
const (
DefaultMaxRetryTime = 3 // 默认最大重试次数
DefaultInterval = 1 // 默认重试间隔(单位秒)
)
// 定义重试参数接口
type Option func(*Config)
// 设定重试参数方法-超时时间
func MaxRetryTime(maxRetryTime int) Option {
return func(config *Config) {
config.MaxRetryTime = maxRetryTime
}
}
// 设定重试参数方法-重试间隔
func Interval(interval int) Option {
return func(config *Config) {
config.Interval = interval
}
}
通用重试方法
// 重试模板方法定义,必须返回错误,且只有一个返回值
type RetryFunc func() error
// 接受重试方法和可选重试参数(重试次数、重试间隔)
func DO(f RetryFunc, options...Option) error{
// 构造默认重试配置
config := NewDefaultConfig()
for i :=range options {
options[i](config)
}
// 接受方法返回错误
var err error
for i := 0;i < config.MaxRetryTime ;i++ {
err = f()
fmt.Printf("第%d次执行 结果%v\n",i+1, err)
if err == nil {
// 执行成功返回
return nil
}
// 发生错误,延迟重试间隔
time.Sleep(time.Duration(config.Interval) * time.Second)
}
return err
}
测试方法
// 获取商和余数
func GetShangAndYushu(a int, b int) (int, int, error) {
val1 := a/b
val2 := a %b
return val1, val2, errors.New("手动触发错误")
// return val1, val2, nil
}
使用示例
func main() {
var shang int // 商
var yushu int // 余数
var err error
DO(func () error {
shang, yushu, err = GetShangAndYushu(2,1)
return err
}, MaxRetryTime(10), Interval(2))
fmt.Printf("最终结果err=%v,shang=%d,yushu=%d\n", err,shang,yushu)
}
结果展示
第1次执行 结果手动触发错误
第2次执行 结果手动触发错误
第3次执行 结果手动触发错误
第4次执行 结果手动触发错误
第5次执行 结果手动触发错误
第6次执行 结果手动触发错误
第7次执行 结果手动触发错误
^@第8次执行 结果手动触发错误
第9次执行 结果手动触发错误
第10次执行 结果手动触发错误
最终结果err=手动触发错误,shang=2,yushu=0