Golang函数重试机制实现代码

 更新时间:2024年04月23日 10:14:21   作者:alden_ygq  
在编写应用程序时,有时候会遇到一些短暂的错误,例如网络请求、服务链接终端失败等,这些错误可能导致函数执行失败,这篇文章主要介绍了Golang函数重试机制实现代码,需要的朋友可以参考下

前言

在编写应用程序时,有时候会遇到一些短暂的错误,例如网络请求、服务链接终端失败等,这些错误可能导致函数执行失败。
但是如果稍后执行可能会成功,那么在一些业务场景下就需要重试了,重试的概念很简单,这里就不做过多阐述了

最近也正好在转golang语言,重试机制正好可以拿来练手,重试功能一般需要支持以下参数

  • execFunc:需要被执行的重试的函数
  • interval:重试的间隔时长
  • attempts:尝试次数
  • conditionMode:重试的条件模式,error和bool模式(这个参数用于控制传递的执行函数返回值类型检测

代码

package retryimpl
import (
	"fmt"
	"time"
)
// RetryOptionV2 配置选项函数
type RetryOptionV2 func(retry *RetryV2)
// RetryFunc 不带返回值的重试函数
type RetryFunc func() error
// RetryFuncWithData 带返回值的重试函数
type RetryFuncWithData func() (any, error)
// RetryV2 重试类
type RetryV2 struct {
	interval time.Duration // 重试的间隔时长
	attempts int           // 重试次数
}
// NewRetryV2 构造函数
func NewRetryV2(opts ...RetryOptionV2) *RetryV2 {
	retry := RetryV2{
		interval: DefaultInterval,
		attempts: DefaultAttempts,
	}
	for _, opt := range opts {
		opt(&retry)
	}
	return &retry
}
// WithIntervalV2 重试的时间间隔配置
func WithIntervalV2(interval time.Duration) RetryOptionV2 {
	return func(retry *RetryV2) {
		retry.interval = interval
	}
}
// WithAttemptsV2 重试的次数
func WithAttemptsV2(attempts int) RetryOptionV2 {
	return func(retry *RetryV2) {
		retry.attempts = attempts
	}
}
// DoV2 对外暴露的执行函数
func (r *RetryV2) DoV2(executeFunc RetryFunc) error {
	fmt.Println("[Retry.DoV2] begin execute func...")
	retryFuncWithData := func() (any, error) {
		return nil, executeFunc()
	}
	_, err := r.DoV2WithData(retryFuncWithData)
	return err
}
// DoV2WithData 对外暴露知的执行函数可以返回数据
func (r *RetryV2) DoV2WithData(execWithDataFunc RetryFuncWithData) (any, error) {
	fmt.Println("[Retry.DoV2WithData] begin execute func...")
	n := 0
	for n < r.attempts {
		res, err := execWithDataFunc()
		if err == nil {
			return res, nil
		}
		n++
		time.Sleep(r.interval)
	}
	return nil, nil
}

测试验证

package retryimpl
import (
	"errors"
	"fmt"
	"testing"
	"time"
)
// TestRetryV2_DoFunc
func TestRetryV2_DoFunc(t *testing.T) {
	testSuites := []struct {
		exceptExecCount int
		actualExecCount int
	}{
		{exceptExecCount: 3, actualExecCount: 0},
		{exceptExecCount: 1, actualExecCount: 1},
	}
	for _, testSuite := range testSuites {
		retry := NewRetryV2(
			WithAttemptsV2(testSuite.exceptExecCount),
			WithIntervalV2(1*time.Second),
		)
		err := retry.DoV2(func() error {
			fmt.Println("[TestRetry_DoFuncBoolMode] was called ...")
			if testSuite.exceptExecCount == 1 {
				return nil
			}
			testSuite.actualExecCount++
			return errors.New("raise error")
		})
		if err != nil {
			t.Errorf("[TestRetryV2_DoFunc] retyr.DoV2 execute failed and err:%+v", err)
			continue
		}
		if testSuite.actualExecCount != testSuite.exceptExecCount {
			t.Errorf("[TestRetryV2_DoFunc] got actualExecCount:%v != exceptExecCount:%v", testSuite.actualExecCount, testSuite.exceptExecCount)
		}
	}
}
// TestRetryV2_DoFuncWithData
func TestRetryV2_DoFuncWithData(t *testing.T) {
	testSuites := []struct {
		exceptExecCount int
		resMessage      string
	}{
		{exceptExecCount: 3, resMessage: "fail"},
		{exceptExecCount: 1, resMessage: "ok"},
	}
	for _, testSuite := range testSuites {
		retry := NewRetryV2(
			WithAttemptsV2(testSuite.exceptExecCount),
			WithIntervalV2(1*time.Second),
		)
		res, err := retry.DoV2WithData(func() (any, error) {
			fmt.Println("[TestRetryV2_DoFuncWithData] DoV2WithData was called ...")
			if testSuite.exceptExecCount == 1 {
				return testSuite.resMessage, nil
			}
			return testSuite.resMessage, errors.New("raise error")
		})
		if err != nil {
			t.Errorf("[TestRetryV2_DoFuncWithData] retyr.DoV2 execute failed and err:%+v", err)
			continue
		}
		if val, ok := res.(string); ok && val != testSuite.resMessage {
			t.Errorf("[TestRetryV2_DoFuncWithData] got unexcept result:%+v", val)
			continue
		}
		t.Logf("[TestRetryV2_DoFuncWithData] got result:%+v", testSuite.resMessage)
	}
}

参考:GitCode - 开发者的代码家园

到此这篇关于Golang函数重试机制实现的文章就介绍到这了,更多相关Golang重试机制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Go中阻塞以及非阻塞操作实现(Goroutine和main Goroutine)

    Go中阻塞以及非阻塞操作实现(Goroutine和main Goroutine)

    本文主要介绍了Go中阻塞以及非阻塞操作实现(Goroutine和main Goroutine),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-05-05
  • Go语言中的匿名结构体用法实例

    Go语言中的匿名结构体用法实例

    这篇文章主要介绍了Go语言中的匿名结构体用法,实例分析了匿名结构体的使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-02-02
  • 一些关于Go程序错误处理的相关建议

    一些关于Go程序错误处理的相关建议

    错误处理在每个语言中都是一项重要内容,众所周知,通常写程序时遇到的分为异常与错误两种,Golang中也不例外,这篇文章主要给大家介绍了一些关于Go程序错误处理的相关建议,需要的朋友可以参考下
    2021-09-09
  • go使用consul实现服务发现及配置共享实现详解

    go使用consul实现服务发现及配置共享实现详解

    这篇文章主要为大家介绍了go使用consul实现服务发现及配置共享实现详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • 详解Golang并发控制的三种方案

    详解Golang并发控制的三种方案

    本文主要介绍了详解Golang并发控制的三种方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-06-06
  • 详解如何通过Go来操作Redis实现简单的读写操作

    详解如何通过Go来操作Redis实现简单的读写操作

    作为最常用的分布式缓存中间件——Redis,了解运作原理和如何使用是十分有必要的,今天来学习如何通过Go来操作Redis实现基本的读写操作,需要的朋友可以参考下
    2023-09-09
  • golang中context的作用详解

    golang中context的作用详解

    这篇文章主要介绍了golang中context的作用,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • Go语言利用excelize库自动化操作Excel的实战指南

    Go语言利用excelize库自动化操作Excel的实战指南

    这篇文章主要为大家详细介绍了如何使用Go语言自动化操作Excel,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下吧
    2026-03-03
  • go实现自动复制U盘小工具demo

    go实现自动复制U盘小工具demo

    这篇文章主要为大家介绍了go实现自动复制U盘小工具demo,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • Golang 文件操作:删除指定的文件方式

    Golang 文件操作:删除指定的文件方式

    这篇文章主要介绍了Golang 文件操作:删除指定的文件方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04

最新评论