Skip to content
Go to file

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

Retry Build Status Go Report Card GoDoc Coverage Status

Lego Batman gif retry

Retry is a Go package which wraps a function and invokes it repeatedly, until it succeeds - not returning an error. Multiple retry-able options are provided, based on number of attempts, delay options between attempts, errors to retry on or ignore, post attempts callback etc. Usable for interaction with flaky web services and similar unreliable sources of frustration.


go get -u


In the simplest and default configuration only about calling package level function Do(), with the desired function. If the failed function fails after 10 retries a custom error of Max Attempts reached is returned. An alternative is using a reusable Retryer value struct (=instance in OOP), which will be reset after each Do() method call.

import "external"

func poll() error{
    return external.IsItDone() 
// equivalent calls
err1 := retry.Do(poll)
err2 := retry.New().Do(poll)
r := retry.New()
err3 := r.Do(poll)

The usual usage would be to use either directly function, which returns an error or wrap the function call with a function, which sets the error according to the inner function output.

// can be used directly
func poll() error{
    return external.IsItDone() 

// has to be wrapped
func pollNoError bool{
    return external.HasItSucceeded()

func wrappedPoll() error{
    if !pollNoError(){
        return errors.New("pollNoError has failed")
    return nil

result := retry.Do(wrappedPoll)

Options on Retryer (listed below in greater detail):

  • constant sleep delay after a failure
  • custom function sleep delay (e.g. exponential back off)
  • recovery of panics
  • calling ensure function, regardless of the Retryer's work inside, once that it finishes
  • calling a custom function after each failure
  • ignoring certain errors
  • retrying only on certain errors

Constant delay of of 100ms between failing attempts

func poll() error { return external.IsItDone() }
err := retry.New(retry.Sleep(100))
result := r.Do(poll)

Using an exponential back off (or any other custom function) after each failed attempt

func poll() error { return external.IsItDone() }
sleepFn := func(attempts int) {
    sleep := time.Duration(2^attempts) * time.Millisecond

err := retry.New(retry.SleepFn(sleepFn)).Do(poll)

Calling an ensure function, which is called after whole Retryer execution

func poll() error { return external.IsItDone() }
func ensure(err error){
    fmt.Println("ensure will be called regardless of err value")

err := retry.Do(poll, retry.Ensure(ensure))

Ignoring failures with errors of listed types (whitelist) and considering them as success

type MyError struct {}

func (e MyError) Error() string { return "this is my custom error" }
func poll() error { return external.IsItDone() }
err := retry.New(Not([]errors{MyError{}})).Do(poll)

Retrying only on listed error types (blacklist), other errors will be considered as success

type MyError struct {}

func (e MyError) Error() string { return "this is my custom error" }

func poll() error { return external.IsItDone() }
err := retry.New(On([]errors{MyError{}})).Do(poll)

Retry allows to combine many options in one Retryer. The code block below will enable:

  • recovery of panics
  • attempting to call the function up to 15 times
  • sleeping for 200 ms after each failed attempt
  • printing the failures to the Stdout
func poll() error { return external.IsItDone() }
failCallback := func(err error){ fmt.Println("failed with error", error) }

r := retry.New(retry.Sleep(200), retry.Tries(15), retry.Recover(), retry.AfterEachFail(failCallback)
err := r.Do(poll)




Configurable Go retry package, which invokes flaky functions until they succeed.





You can’t perform that action at this time.