How to cacth if Goroutine finished and close error channel?

Issue

In below code snipped I’m trying to loop some data and for each iteration start new go routine. I have created error channel and if some errors appear goroutine it should write it to the channel. So I have 2 questions:

  1. How to catch if all goroutines done and close error channel for breaking from "for" loop to continue main function execution?
  2. if in each routine I’ll call some functions which appends values to global variables will there be any issues with race condition? If yes, how to handle this.
package main

import (
    "fmt"
)

var errc = make(chan error, 15)


func fetchAll() {
    var N = 15
    for i := 0; i < N; i++ {
        go func(i int) {
            err := error(nil)
            if err != nil {
                errc <- err
            }
            // Doing some stuff there
            fmt.Println(i)
        }(i)
    }
}

func main() {
    fetchAll()
    for {
        select {
        case err := <-errc:
            fmt.Println(err)
            break
        }
    }
    fmt.Println("Finished All")

}

Solution

Use a WaitGroup:

wg:=sync.WaitGroup{}
for i := 0; i < N; i++ {
    wg.Add(1)
    go func(i int) {
       defer wg.Done()
       err := error(nil)
       if err != nil {
           errc <- err
       }
       // Doing some stuff there
       fmt.Println(i)
    }(i)
}
go func() {
   wg.Wait()
   close(errc)
}

Then you can change the loop in main. This loop will terminate when the channel is closed.

for err:=range errc {
  fmt.Println(err)
}

If you have variables shared between goroutines, use a sync.Mutex shared among goroutines to control read/write to those variables, otherwise you’ll run into race conditions.

Answered By – Burak Serdar

Answer Checked By – Dawn Plyler (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.