pkaramol
pkaramol

Reputation: 19342

Use channels to implement retry mechanism in go

I am launching two concurrent execution paths (a.k.a. goroutines) to perform two jobs


    const Retries = 10

    wg.Add(2)
    go func() {
        for i := 0; i < Retries; i++ {
            retVal1, err1 = doSomeWork()
            if err1 != nil {
                fmt.Printf("WARNING: Error job in attempt no %d: %s - retrying...\n", i+1, err1)
                continue
            } else {
                break
            }
        }
        if err1 != nil {
            log.Fatalf("ERROR job %s\n", err1)
        }
        wg.Done()
    }()
    go func() {
        for i := 0; i < Retries; i++ {
            retVal2, err2 = doSomeWork()
            if err2 != nil {
                fmt.Printf("WARNING: Error job in attempt no %d: %s - retrying...\n", i+1, err2)
                continue
            } else {
                break
            }
        }
        if err2 != nil {
            log.Fatalf("ERROR job %s\n", err2)
        }
        wg.Done()
    }()
    wg.Wait()

My question is (apart from importing some third-party retry library) whether there is more go-idiomatic way to structure the above code? Would a channel / select approach be more go-centric?

Upvotes: 1

Views: 1195

Answers (1)

chmike
chmike

Reputation: 22154

Your code is not that bad. Using channels would be an overkill.

I would write it this way which is slightly lighter.

const maxRetries int = 3

go func() {
    var retries int
    for {
        retVal1, err1 = doSomeWork()
        if err1 == nil {
            break
        }
        retries++
        if retries == maxRetries {
            log.Fatalf("ERROR job %s\n", err1)
        }
        fmt.Printf("WARNING: Error job in attempt no %d: %s - retrying...\n", retries, err1)
    }
    wg.Done()
}()

Upvotes: 1

Related Questions