title: golang sync.WaitGroup never completes
body: <p>I have the below code that fetches a list of URL's and then conditionally downloads a file and saves it to the filesystem. The files are fetched concurrently and the main goroutine waits for all the files to be fetched. But, the program <strong>never exits</strong> (and there are no errors) after completing all the requests.</p>
  
  <p>What I think is happening is that somehow the amount of go routines in the <code>WaitGroup</code> is either incremented by too many to begin with (via <code>Add</code>) or not decremented by enough (a <code>Done</code> call is not happening).</p>
  
  <p>Is there something I am obviously doing wrong? How would I inspect how many go routines are presently in the <code>WaitGroup</code> so I can better debug what's happening?</p>
  
  <pre><code>package main
  
  import (
      "fmt"
      "io"
      "io/ioutil"
      "net/http"
      "os"
      "strings"
      "sync"
  )
  
  func main() {
      links := parseLinks()
  
      var wg sync.WaitGroup
  
      for _, url := range links {
          if isExcelDocument(url) {
              wg.Add(1)
              go downloadFromURL(url, wg)
          } else {
              fmt.Printf("Skipping: %v \n", url)
          }
      }
      wg.Wait()
  }
  
  func downloadFromURL(url string, wg sync.WaitGroup) error {
      tokens := strings.Split(url, "/")
      fileName := tokens[len(tokens)-1]
      fmt.Printf("Downloading %v to %v \n", url, fileName)
  
      content, err := os.Create("temp_docs/" + fileName)
      if err != nil {
          fmt.Printf("Error while creating %v because of %v", fileName, err)
          return err
      }
  
      resp, err := http.Get(url)
      if err != nil {
          fmt.Printf("Could not fetch %v because %v", url, err)
          return err
      }
      defer resp.Body.Close()
  
      _, err = io.Copy(content, resp.Body)
      if err != nil {
          fmt.Printf("Error while saving %v from %v", fileName, url)
          return err
      }
  
      fmt.Printf("Download complete for %v \n", fileName)
  
      defer wg.Done()
      return nil
  }
  
  func isExcelDocument(url string) bool {
      return strings.HasSuffix(url, ".xlsx") || strings.HasSuffix(url, ".xls")
  }
  
  func parseLinks() []string {
      linksData, err := ioutil.ReadFile("links.txt")
      if err != nil {
          fmt.Printf("Trouble reading file: %v", err)
      }
  
      links := strings.Split(string(linksData), ", ")
  
      return links
  }
  </code></pre>