Idiomatic Go retry package. Thanks to @rowland for code review.
go get gopkg.in/matryer/try.v1
or
drop gopkg.in/matryer/try.v1
- Learn more about Drop
Just call try.Do with the function you want to retry in the event of an error:
- Call
try.Dothat returns aboolindicating whether to retry or not, and anerror - The
attemptargument will start at 1 and count up try.Doblocks until you returnfalse, or anilerrortry.Doreturns the last error ornilif it was successful
var value string
err := try.Do(func(attempt int) (bool, error) {
var err error
value, err = SomeFunction()
return attempt < 5, err // try 5 times
})
if err != nil {
log.Fatalln("error:", err)
}
In the above example the function will be called repeatedly until error is nil, while attempt < 5 (i.e. try 5 times)
Try supports retrying in the event of a panic.
- Use named return parameters
- Set
retryfirst - Defer the recovery code, and set
errmanually in the case of a panic - Use empty
returnstatement at the end
var value string
err := try.Do(func(attempt int) (retry bool, err error) {
retry = attempt < 5 // try 5 times
defer func() {
if r := recover(); r != nil {
err = errors.New(fmt.Sprintf("panic: %v", r))
}
}()
value, err = SomeFunction()
return
})
if err != nil {
log.Fatalln("error:", err)
}
To introduce a delay between retries, just make a time.Sleep call before you return from the function if you are returning an error.
var value string
err := try.Do(func(attempt int) (bool, error) {
var err error
value, err = SomeFunction()
if err != nil {
time.Sleep(1 * time.Minute) // wait a minute
}
return attempt < 5, err
})
if err != nil {
log.Fatalln("error:", err)
}
To avoid infinite loops, Try will ensure it only makes try.MaxRetries attempts. By default, this value is 10, but you can change it:
try.MaxRetries = 20
To see if a Do operation failed due to reaching the limit, you can check the error with try.IsMaxRetries(err).