Fragment Description:



Synchronization, study 2:
the sync.WaitGroup type.
Using sync.WaitGroup, an essential idiom to manage that all concurrent goroutines are properly completed.
See '//WAITGROUP DEF-x' in this example.
Package sync provides basic synchronization primitives such as locks and condition variables, semaphores must be implemented by the user.
The package proposes the Cond, Locker, Mutex, Once, Pool, RWMutex and WaitGroup types.
These are low-level primitives to support various synchronization schemes.
Higher-level synchronization is better done via channels and communication.


goroutinesSyncWithWaitGroup

Go Playground

Last update, on 2015, Tue 17 Nov, 18:25:00

/* ... <== see fragment description ... */

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "sync"
)

func main() {
    urls := []string{
        "http://www.reddit.com/r/programming.go",
        "http://www.reddit.com/r/learngolang/",
    }
    jsonResponses := make(chan string)

    var wg sync.WaitGroup //WAITGROUP DEF-1
    wg.Add(len(urls))     //WAITGROUP DEF-2

    for _, url := range urls {
        // as many goroutines as there are urls
        // note the way each goroutine receives its url parameter
        go func(url string) {
            defer wg.Done() //WAITGROUP DEF-3
            res, err := http.Get(url)
            if err != nil {
                log.Fatal(err)
            } else {
                defer res.Body.Close()
                body, err := ioutil.ReadAll(res.Body)
                if err != nil {
                    log.Fatal(err)
                } else {
                    jsonResponses <- string(body) //send on the channel
                }
            }
        }(url)
    }
    // Wait() will block until all goroutines started within the WaitGroup are
    // finished. Then we can close the channel(s) used to communicate
    go func() {
        wg.Wait()            //WAITGROUP DEF-4
        close(jsonResponses) // not closed, the following 'range' would never end
    }()
    // A range over a channel is terminated when the channel is closed
    for response := range jsonResponses {
        fmt.Println(response)
    }
}

/* Expected Output
A list of .... text in json format.
*/



Comments