脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|shell|

服务器之家 - 脚本之家 - Golang - Golang函数重试机制实现代码

Golang函数重试机制实现代码

2024-04-23 16:21alden_ygq Golang

在编写应用程序时,有时候会遇到一些短暂的错误,例如网络请求、服务链接终端失败等,这些错误可能导致函数执行失败,这篇文章主要介绍了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重试机制内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/ygq13572549874/article/details/137885134

延伸 · 阅读

精彩推荐
  • GolangWindows下使用go语言写程序安装配置实例

    Windows下使用go语言写程序安装配置实例

    这篇文章主要介绍了Windows下使用go语言写程序安装配置实例,本文讲解了安装go语言、写go代码、生成可执行文件、批量生成可执行文件等内容,需要的朋友可...

    脚本之家2382020-04-24
  • GolangGo语言异常处理(Panic和recovering)用法详解

    Go语言异常处理(Panic和recovering)用法详解

    异常处理是程序健壮性的关键,往往开发人员的开发经验的多少从异常部分处理上就能得到体现。Go语言中没有Try Catch Exception机制,但是提供了panic-and-re...

    孙琦Ray9642022-07-13
  • GolangGo中sync 包Cond使用场景分析

    Go中sync 包Cond使用场景分析

    Cond 是和某个条件相关,在条件还没有满足的时候,所有等待这个条件的协程都会被阻塞住,只有这个条件满足的时候,等待的协程才可能继续进行下去,...

    水淹萌龙7902023-03-05
  • Golang一文教你如何优雅处理Golang中的异常

    一文教你如何优雅处理Golang中的异常

    我们在使用Golang时,不可避免会遇到异常情况的处理,与Java、Python等语言不同的是,Go中并没有try...catch...这样的语句块,这个时候我们如何才能更好的处...

    阿拉懒神灯7882022-12-02
  • GolangGo中如何使用set的方法示例

    Go中如何使用set的方法示例

    这篇文章主要介绍了Go中如何使用set的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面...

    波罗学3152020-05-28
  • Golanggo micro集成链路跟踪的方法和中间件原理解析

    go micro集成链路跟踪的方法和中间件原理解析

    这篇文章主要介绍了go-micro集成链路跟踪的方法和中间件原理,关于Http或者说是Restful服务的链路跟踪,go-micro的httpClient支持CallWrapper,可以用WrapCall来添加链...

    波斯马11712022-09-30
  • Golanggo语言Timer计时器的用法示例详解

    go语言Timer计时器的用法示例详解

    Go语言的标准库里提供两种类型的计时器Timer和Ticker。这篇文章通过实例代码给大家介绍go语言Timer计时器的用法,代码简单易懂,感兴趣的朋友跟随小编一...

    网管叨bi叨6092020-07-08
  • GolangGolang分布式锁简单案例实现流程

    Golang分布式锁简单案例实现流程

    分布式锁是控制分布式系统之间同步访问共享资源的一种方式。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源...

    kina1007652022-12-15