4 回答

TA貢獻(xiàn)1841條經(jīng)驗(yàn) 獲得超3個(gè)贊
我進(jìn)行更簡(jiǎn)單的重試。
使用更簡(jiǎn)單的循環(huán)邏輯來(lái)確保正確性。
我們?cè)趫?zhí)行重試之前會(huì)睡覺(jué),因此請(qǐng)用作睡眠的條件。
i > 0
代碼如下:
func retry(attempts int, sleep time.Duration, f func() error) (err error) {
for i := 0; i < attempts; i++ {
if i > 0 {
log.Println("retrying after error:", err)
time.Sleep(sleep)
sleep *= 2
}
err = f()
if err == nil {
return nil
}
}
return fmt.Errorf("after %d attempts, last error: %s", attempts, err)
}

TA貢獻(xiàn)1816條經(jīng)驗(yàn) 獲得超6個(gè)贊
我知道這是一個(gè)古老的問(wèn)題,但在搜索重試時(shí)遇到了它,并將其用作解決方案的基礎(chǔ)。
此版本可以接受具有 2 個(gè)返回值的函數(shù),并在 golang 1.18 中使用泛型來(lái)實(shí)現(xiàn)這一點(diǎn)。我在1.17中嘗試過(guò),但無(wú)法找到使該方法通用的方法。
這可以擴(kuò)展到任何類(lèi)型的任意數(shù)量的返回值。我在這里使用過(guò),但可以限制為類(lèi)型列表。any
func retry[T any](attempts int, sleep int, f func() (T, error)) (result T, err error) {
for i := 0; i < attempts; i++ {
if i > 0 {
log.Println("retrying after error:", err)
time.Sleep(time.Duration(sleep) * time.Second)
sleep *= 2
}
result, err = f()
if err == nil {
return result, nil
}
}
return result, fmt.Errorf("after %d attempts, last error: %s", attempts, err)
}
用法示例:
var config Configuration
something, err := retry(config.RetryAttempts, config.RetrySleep, func() (Something, error) { return GetSomething(config.Parameter) })
func GetSomething(parameter string) (something Something, err error) {
// Do something flakey here that might need a retry...
return something, error
}
希望這能幫助與我具有相同用例的人。

TA貢獻(xiàn)1803條經(jīng)驗(yàn) 獲得超6個(gè)贊
您正在調(diào)用的函數(shù)正在使用上下文。因此,處理該上下文非常重要。
如果您不知道上下文是什么以及如何使用它,我會(huì)推薦該帖子:https://blog.golang.org/context
重試函數(shù)還應(yīng)處理上下文。只是為了讓你走上正軌,我給你一個(gè)簡(jiǎn)單的實(shí)現(xiàn)。
func retryMyServiceFunction(ctx context.Context, place uint, length uint, sleep time.Duration) {
for {
select {
case ctx.Done():
return
default:
err := MyServiceFunction(ctx, place, length)
if err != nil {
log.Println("handle error here!", err)
time.Sleep(sleep)
} else {
return
}
}
}
}
我不喜歡睡眠部分。因此,您應(yīng)該分析返回的錯(cuò)誤。此外,您還必須考慮超時(shí)。當(dāng)您讓服務(wù)長(zhǎng)時(shí)間休眠時(shí),可能會(huì)有超時(shí)。

TA貢獻(xiàn)1155條經(jīng)驗(yàn) 獲得超0個(gè)贊
在GoPlayground中接受的答案的評(píng)論中,我會(huì)考慮添加一些東西。在 for 循環(huán)中使用 continue 和 break 會(huì)使循環(huán)更加簡(jiǎn)單,因?yàn)椴皇褂迷撜Z(yǔ)句。此外,我會(huì)在所有函數(shù)中使用早期返回來(lái)直接返回錯(cuò)誤。最后,我會(huì)一直使用錯(cuò)誤來(lái)檢查函數(shù)是否失敗,檢查值的有效性應(yīng)該在執(zhí)行的函數(shù)本身內(nèi)部。if i > 0 {
這將是我的小嘗試:
package main
import (
"errors"
"fmt"
"log"
"time"
)
func main() {
var complicatedFunctionPassing bool = false
var attempts int = 5
// if complicatedFunctionPassing is true retry just makes one try
// if complicatedFunctionPassing is false retry makes ... attempts
err := retry(attempts, time.Second, func() (err error) {
if !complicatedFunctionPassing {
return errors.New("somthing went wrong in the important function")
}
log.Println("Complicated function passed")
return nil
})
if err != nil {
log.Printf("failed after %d attempts with error: %s", attempts, err.Error())
}
}
func retry(attempts int, sleep time.Duration, f func() error) (err error) {
for i := 0; i < attempts; i++ {
fmt.Println("This is attempt number", i+1)
// calling the important function
err = f()
if err != nil {
log.Printf("error occured after attempt number %d: %s", i+1, err.Error())
log.Println("sleeping for: ", sleep.String())
time.Sleep(sleep)
sleep *= 2
continue
}
break
}
return err
}
你可以在這里嘗試一下:https://go.dev/play/p/Ag8ObCb980U
- 4 回答
- 0 關(guān)注
- 161 瀏覽
添加回答
舉報(bào)