In applications that are i/o heavy, it can get clunky to synchronously execute high-latency functions one after the other. For example, if I have a web page that needs to request 7 files from the server before it can show the page, I need to asynchronously fetch all those files at the same time. The alternative will take much too long. This is where and come in. PromiseAll WaitGroup Let's take a look at an example of synchronous* JavaScript code: fetch = ( ) { resp = fetch( ) text = resp.text() .log(text) resp2 = fetch( ) text = resp2.text() .log(text) resp3 = fetch( ) text = resp3.text() .log(text) } runSync() const require 'node-fetch' async ( ) function runSync const await 'https://qvault.io' let await console const await 'https://github.com' await console const await 'https://gitlab.io' await console *Note: Due to some technicalities with JavaScript, the above utilizes asynchronous code (see async/await), but for the purposes of our discussion, each fetch() is synchronous in relation to each other. On order to speed this up, we want each network call to the server (the calls) to happen at the same time. Take a look: fetch() fetch = ( ) { promise1 = fetch( ) promise2 = fetch( ) promise3 = fetch( ) .all([promise1, promise2, promise3]).then( (values) => { text = values[ ].text() .log(text) text = values[ ].text() .log(text) text = values[ ].text() .log(text) }); } runAsync() const require 'node-fetch' async ( ) function runAsync const 'https://qvault.io' const 'https://github.com' const 'https://gitlab.io' await Promise async let await 0 console await 1 console await 2 console WaitGroup In Go, we have a similar concept, the standard type. First however, let's take a look at how to synchronously fetch data over the wire: sync package's WaitGroup fetch = ( ) { promise1 = fetch( ) promise2 = fetch( ) promise3 = fetch( ) .all([promise1, promise2, promise3]).then( (values) => { text = values[ ].text() .log(text) text = values[ ].text() .log(text) text = values[ ].text() .log(text) }); } runAsync() const require 'node-fetch' async ( ) function runAsync const 'https://qvault.io' const 'https://github.com' const 'https://gitlab.io' await Promise async let await 0 console await 1 console await 2 console As before, the problem here is that each network call is done in succession, wasting time. Let's use some goroutines, which we start by using the keyword: go main ( ) { getAndPrintData( ) getAndPrintData( ) getAndPrintData( ) } { resp, _ := http.Get(url) buf := (bytes.Buffer) buf.ReadFrom(resp.Body) fmt.Println(buf.String()) } package import "bytes" "fmt" "net/http" func main () go "https://qvault.io" go "https://github.com" go "https://gitlab.io" func getAndPrintData (url ) string new If you ran this code, you will see that nothing is printed and the program exits almost immediately. the problem is that after starting 3 separate goroutines and yielding execution back to the main thread, there is nothing stopping main() from exiting. Once main exits, it cleans up its goroutines before they can get a response. In order to make sure that we wait for all of our functions to complete, but to still allow them to execute at the same time, we use a WaitGroup. main ( ) { wg := sync.WaitGroup{} wg.Add( ) { wg.Done() getAndPrintData( ) }() { wg.Done() getAndPrintData( ) }() { wg.Done() getAndPrintData( ) }() wg.Wait() } { resp, _ := http.Get(url) buf := (bytes.Buffer) buf.ReadFrom(resp.Body) fmt.Println(buf.String()) } package import "bytes" "fmt" "net/http" "sync" func main () 3 go func () defer "https://qvault.io" go func () defer "https://github.com" go func () defer "https://gitlab.io" func getAndPrintData (url ) string new First, we create a WaitGroup, in our case, . Then we use the function to let the WaitGroup know there are 3 counters to wait for. We pass a pointer to the WaitGroup to each goroutine and use the keyword to mark a counter done when each goroutine exits. wg Add() defer In the main thread we use the function to block the main thread until all of the goroutines have exited. Wait() WaitGroups in Go are very similar to PromiseAll in JavaScript and can be a useful tool when developing web client applications. Thanks For Reading Follow us on Twitter if you have any questions or comments @q_vault Take game-like coding courses on Qvault Classroom to our Newsletter for more educational articles Subscribe