我有一个非常简单的脚本,该脚本发出一个get请求,然后对响应进行处理。我有2个版本,其中一个使用go例程,而另一个版本则没有我两个都进行测试,并且速度没有差异。这是我正在做的事情的愚蠢版本:

普通版:

func main() {
    url := "http://finance.yahoo.com/q?s=aapl"

    for i := 0; i < 250; i++ {
        resp, err := http.Get(url)
        if err != nil {
            fmt.Println(err)
        }

        fmt.Println(resp.Status)
    }
}

例行:
func main() {
    url := "http://finance.yahoo.com/q?s=aapl"

    for i := 0; i < 250; i++ {
        wg.Add(1)
        go run(url, &wg)
        wg.Wait()
    }
}

func run(url string, wg *sync.WaitGroup) {
    defer wg.Done()
    resp, err := http.Get(url)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Println(resp.Status)
}

在大多数情况下,当我使用go例程时,程序将花费更长的时间执行。我缺少了解有效使用并发的什么概念?

最佳答案

您的示例的主要问题是您正在for循环中调用wg.Wait()。这将导致执行阻塞,直到您在wg.Done()内部推迟了run调用为止。结果,执行不是并发的,它在goroutine中发生,但是您在启动goroutine i之后和启动i+1之前阻塞了。如果您将该语句放置在循环之后,而不是像下面那样放置,则您的代码要等到循环之后才阻塞(所有goroutine已启动,有些可能已经完成)。

func main() {
    url := "http://finance.yahoo.com/q?s=aapl"

    for i := 0; i < 250; i++ {
        wg.Add(1)
        go run(url, &wg)
        // wg.Wait() don't wait here cause it serializes execution
    }
    wg.Wait() // wait here, now that all goroutines have been started
}

关于go - 我在并发方面缺少什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33616864/

10-13 01:01