如果发生错误,请重复代码

时间:2017-12-02 10:13:21

标签: go

我有一个代码正在进行很长的ETL操作。有时会出现网络问题。我想捕获错误read tcp 10.10.10.10:32423 -> 20.20.20.20:2344: i/o timeout并再次重试该操作。

这是我的代码:

for {
    err := mssql.Db.ProcessAllData(true, &processedAsutpIds, filename)
    if err == nil {
      fmt.Println("done.")
      os.Exit(0)
    } else {
      fmt.Println(err.Error())
      fmt.Println("!!!! Error occurred - sleep for 5 minutes")
      time.Sleep(time.Minute * 5)
    }
}

是否有可能以更惯用的方式重写它?

2 个答案:

答案 0 :(得分:1)

我看到的唯一改进是:

for {
    err := mssql.Db.ProcessAllData(true, &processedAsutpIds, filename)
    if err == nil {
        fmt.Println("done.")
        os.Exit(0)
    }
    fmt.Println(err.Error())
    fmt.Println("!!!! Error occurred - sleep for 5 minutes")
    time.Sleep(time.Minute * 5)
}

即:消除'else',因为它是隐含的。 go vet会告诉你同样的事情。您还应该使用gofmt来更正缩进。

您可能还想检查特定错误,并仅继续发生网络错误。但这是一个应用决定。

答案 1 :(得分:1)

您可以考虑重试功能,例如Alexandre Bourget在“My favorite #golang retry function”中描述的功能:

    var signedContent []byte
    err := retry(5, 2*time.Second, func() (err error) {
        signedContent, err = signFile(unsignedFile, contents)
        return
    })
    if err != nil {
        log.Println(err)
        http.Error(w, err.Error(), 500)
        return
    }

重试功能为:

func retry(attempts int, sleep time.Duration, f func() error) (err error) {
    for i := 0; ; i++ {
        err = f()
        if err == nil {
            return
        }

        if i >= (attempts - 1) {
            break
        }

        time.Sleep(sleep)

        log.Println("retrying after error:", err)
    }
    return fmt.Errorf("after %d attempts, last error: %s", attempts, err)
}