我有一个非常简单的脚本,该脚本发出一个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/