【问题标题】:Turn Retry Policy into Reusable Function将重试策略变为可重用函数
【发布时间】:2019-04-24 18:45:27
【问题描述】:

我们的项目有一个简单的重试策略:

  1. 出现第一个错误时,休眠 1 秒。
  2. 第二个错误,休眠 5 秒。
  3. 第三个错误,休眠 10 秒。
  4. 在第四个错误时,退出重试并返回错误。

我们的重试策略如下所示:

package main

import (
    "errors"  
    "fmt"         
    "time"    
)

func main() {
    errorCount := 0
    var err error

    fmt.Println("start!")

    for {
        err = generateError()
        if err != nil {
            if errorCount == 0 {
                fmt.Println("sleeping for 1 second...")
                time.Sleep(1 * time.Second)    
            } else if errorCount == 1 {
                fmt.Println("sleeping for 5 seconds...")
                time.Sleep(5 * time.Second)    
            } else if errorCount == 2 {
                fmt.Println("sleeping for 10 seconds...")
                time.Sleep(10 * time.Second)    
            } else {
                fmt.Println("giving up...")
                break
            }

            errorCount++
        } else {
            fmt.Println("no errors!")
            break
        }
    }

    fmt.Println("error:", err)
    fmt.Println("done!")
}

func generateError() error {
    err := errors.New("something happened")
    return err
}

有没有办法把上面的代码变成可复用的函数?

【问题讨论】:

    标签: go retrypolicy


    【解决方案1】:

    只需将 generateError 作为参数传递(我简化了重试函数,因为我情不自禁):

    package main
    
    import (
        "errors"
        "fmt"
        "time"
    )
    
    func main() {
        retry(generateError)
    }
    
    func retry(f func() error) {
        fmt.Println("start!")
    
        backoff := []time.Duration{
            1 * time.Second,
            5 * time.Second,
            10 * time.Second,
        }
    
        var err error
        for _, d := range backoff {
            err = f()
            if err != nil {
                fmt.Printf("sleeping for %v...\n", d)
                time.Sleep(d)
            } else {
                fmt.Println("no errors!")
                return
            }
        }
    
        fmt.Println("error:", err)
        fmt.Println("done!")
    }
    
    func generateError() error {
        err := errors.New("something happened")
        return err
    }
    

    【讨论】:

    • 这正是我想要的!谢谢! (附言我将Println 行更改为fmt.Printf("sleeping for %v...\n", d) 以处理格式)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-31
    • 1970-01-01
    相关资源
    最近更新 更多