将重试策略变成可重用的函数

Turn Retry Policy into Reusable Function

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

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

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

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
}

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

只需将 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
}