CodeBlanks Logo Icon CodeBlanks

Error handling

Add error handling in workers and a WaitGroup.

Error handling and shutdown

When a job fails there are two options: report the error with the result and continue, or stop all jobs at the first error. For the second, golang.org/x/sync/errgroup is ideal:

g, ctx := errgroup.WithContext(ctx)
g.SetLimit(3)  // at most 3 concurrent jobs
for _, yol := range dosyalar {
    g.Go(func() error { return isle(ctx, yol) })
}
if err := g.Wait(); err != nil {
    log.Println("ilk hata:", err)
}

The first error cancels ctx; the other jobs check ctx and stop early.

Joining errors

If you want "try every job, show all errors at the end", collect the errors and turn them into one with errors.Join (Go 1.20):

var hatalar []error
for s := range sonuclar {
    if s.Hata != nil {
        hatalar = append(hatalar, fmt.Errorf("iş %d: %w", s.IsID, s.Hata))
    }
}
return errors.Join(hatalar...)  // nil if there are none

errors.Is can still find every error inside the joined error.

Practice Collecting errors

Run three jobs; the job with ID 1 returns errors.New("okunamadı"). Wrap the errors from the results with fmt.Errorf("iş %d: %w", ...), collect them and print the result of errors.Join.

Starter code

main.go
package main

import (
    "errors"
    "fmt"
    "sync"
)

func main() {
    // buraya yaz
}

Sample solution

main.go
package main

import (
    "errors"
    "fmt"
    "sync"
)

type Sonuc struct {
    IsID int
    Hata error
}

func main() {
    sonuclar := make(chan Sonuc)
    var wg sync.WaitGroup
    for i := 0; i < 3; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            var err error
            if id == 1 {
                err = errors.New("okunamadı")
            }
            sonuclar <- Sonuc{id, err}
        }(i)
    }
    go func() {
        wg.Wait()
        close(sonuclar)
    }()
    var hatalar []error
    for s := range sonuclar {
        if s.Hata != nil {
            hatalar = append(hatalar, fmt.Errorf("iş %d: %w", s.IsID, s.Hata))
        }
    }
    fmt.Println(errors.Join(hatalar...))
}

Expected output

iş 1: okunamadı

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 What does <code>g.Wait()</code> return in an errgroup?

  • The first non-nil error Correct answer
  • A list of all errors
  • The last error
  • Always nil

Explanation: errgroup keeps the first error and Wait returns it; if all errors are needed, use the result-channel approach or errors.Join.

2 Join the errors

Question
return errors.____(hatalar...)
Answer
return errors.Join(hatalar...)

Explanation: errors.Join merges several errors into one; with an empty list it returns nil.

3 Strategy

Term Meaning
Sonuc.Hata Report the error, continue
errgroup Stop at the first error
errors.Join Show all errors
g.SetLimit(3) Concurrency limit

All lessons in Intermediate