Handle goroutines with sync.Waitgroup
If you are gonna do alot of requests at the same time, it could be a good idea to put them in goroutines to be more efficient. I want to show you how you can handle this in a easy way using sync.WaitGroup.
First we create a WaitGroup
variable which we will use to control our goroutines, and a struct that will contain the response from the dog api we are gonna use in this example.
var wg sync.WaitGroup
var img struct {
Status string
Message string
}
Then we create a easy get
request function to test our code:
func randomDogImage(i *img, wg *sync.WaitGroup) {
defer wg.Done() // notice this
resp, err := http.Get("https://dog.ceo/api/breeds/image/random")
if err != nil {
fmt.Errorf("Failed http get request: %v", err)
return
}
defer resp.Body.Close()
err = json.NewDecoder(resp.Body).Decode(i)
if err != nil {
fmt.Errorf("Could not decode json: %v", err)
return
}
}
Notice the defer wg.Done()
.
This will tell the WaitGroup
that this goroutine is “done”. Without calling this function the program will end up in a deadlock, since the WaitGroup
will be forever waiting for the wg.Done()
being called.
Then we can continue like this:
var i1, i2, i3, i4 img
wg.Add(1)
go randomDogImage(&i1, &wg)
wg.Add(1)
go randomDogImage(&i2, &wg)
wg.Add(1)
go randomDogImage(&i3, &wg)
wg.Add(1)
go randomDogImage(&i4, &wg)
wg.Wait()
// This will print when all requests are done
fmt.Println(i1.Message)
fmt.Println(i2.Message)
fmt.Println(i3.Message)
fmt.Println(i4.Message)
wg.Wait()
will wait until all your goroutines are done before continuing.
Thanks for reading.