1

I am currenlty learning GO. After learning some of the basics I have been trying to write a small program that concurrently download webpages (urls in a slice) to different files using goroutines. Here is some code that I wrote:

func downloadFromUrl(url string) {
    tokens := strings.Split(url, "/")
    fileName := tokens[len(tokens)-1]
    // I took out the bit that download the file for testing.
    fmt.Println("Downloading", url, "to", fileName)

}

I commented out the bit that actually downloads the page for testing. In my main function I am doing this:

func main() {
    urls := []string{"http://www.google.com", "http://www.yahoo.com", "http://www.google.com"}

    for _, url := range urls {
        fmt.Println(url);
        go downloadFromUrl(url);
    }
}

The problem is that when I use the expression go downloadFromUrl(url); The function downloadFromUrl does not run. But if I just use downloadFromUrl(url) in the loop it works fine. What am I doing wrong? Do I have to use channel with the routines?

sunkuet02
  • 2,376
  • 1
  • 26
  • 33
awm
  • 1,130
  • 3
  • 17
  • 37
  • 1
    Possible duplicate of 1. [Whats wrong with this golang code?](http://stackoverflow.com/questions/28958192/whats-wrong-with-this-golang-code) 2. [Goroutine does not execute if time.Sleep included](http://stackoverflow.com/questions/28307783/goroutine-does-not-execute-if-time-sleep-included) – icza May 12 '16 at 03:53

1 Answers1

6

The problem is main exits before your goroutine returns, the easiest solution is to use a sync.WaitGroup.

func main() {
    urls := []string{"http://www.google.com", "http://www.yahoo.com", "http://www.google.com"}
    var wg sync.WaitGroup
    for _, url := range urls {
        wg.Add(1)
        log.Println(url)
        go downloadFromUrl(url, &wg)
    }
    wg.Wait()
}

func downloadFromUrl(url string, wg *sync.WaitGroup) {
    defer wg.Done()
    ....
}
OneOfOne
  • 95,033
  • 20
  • 184
  • 185
  • thanks, this works for me. but can you explain how this works? or refer me to the appropriate documentation. Thanks. – awm May 13 '16 at 18:29
  • @awm when you do `go func()` it runs in the background and execution continues, so basically main() ends because there's nothing running in it. Using a waitgroup will force main to wait. – OneOfOne May 13 '16 at 22:19