Search code examples
loopsgorace-conditionanonymous-functiongoroutine

Go: Anonymous Func Only Taking Last Value in For Range


I imagine this is a pretty easy fix. Just trying loop through the string list urls and print out each url as the loop iterates. But when I add in concurrency (with go and WaitGroup) all it prints out is the last url in the list.

Why is it only printing out the last url (when printed from the anon function) rather than each url individually as the loop iterates?

Go Playground: http://play.golang.org/p/z4IZLY7Mt_


Code:

package main

import (
    "fmt"
    "sync"
)

var urls = []string{
    "http://google.com",
    "http://facebook.com",
    "http://youtube.com",
    "http://yahoo.com",
    "http://baidu.com",
    "http://wikipedia.org",
    "http://twitter.com",
    "http://live.com",
    "http://amazon.com",
    "http://linkedin.com",
    "http://google.co.in",
}

func main() {
    var wg sync.WaitGroup
    for _, url := range urls {
        fmt.Println("correct: " + url)
        wg.Add(1)
        go func() {
            fmt.Println("wrong: " + url)
            wg.Done()
        }()
    }

    wg.Wait()
}

Solution

  • Here is the working code:

    package main
    
    import (
        "fmt"
        "sync"
    )
    
    var urls = []string{
        "http://google.com",
        "http://facebook.com",
        "http://youtube.com",
        "http://yahoo.com",
        "http://baidu.com",
        "http://wikipedia.org",
        "http://twitter.com",
        "http://live.com",
        "http://amazon.com",
        "http://linkedin.com",
        "http://google.co.in",
    }
    
    func main() {
        var wg sync.WaitGroup
        for _, url := range urls {
            fmt.Println("correct: " + url)
            wg.Add(1)
            go func(url string) {
                fmt.Println("wrong: " + url)
                wg.Done()
            }(url)
        }
    
        wg.Wait()
    }
    

    Also on go playground: http://play.golang.org/p/zFSDvfdIDS