Concurrency sync.WaitGroup不等待

Concurrency sync.WaitGroup不等待,concurrency,go,Concurrency,Go,也许我看不到明显的东西,我做错了什么: func printSize (listOfUrls []string){ var wg sync.WaitGroup wg.Add(len(listOfUrl)) for _, myurl := range(listOfUrls){ go func(){ body := getUrlBody(myurl) fmt.Println(len(body))

也许我看不到明显的东西,我做错了什么:

func printSize (listOfUrls []string){
    var wg sync.WaitGroup
    wg.Add(len(listOfUrl))
    for _, myurl := range(listOfUrls){
        go func(){
               body := getUrlBody(myurl)
               fmt.Println(len(body))
               wg.Done()
           }()    
    } 
    wg.Wait()
}
如果我删除wg并转到,我会正确地收到每个url主体的大小。如果我像上面那样做,它几乎立即打印出零。getUrlBody()执行有时需要几分钟的时间

回答评论:可以肯定的是,我也用这种方式尝试过,它表现出了同样的行为。 我发现错误在getUrlBody和main()函数中

func printSize(listOfUrls []string) {
    var wg sync.WaitGroup
    wg.Add(len(listOfUrls))
        for _, myurl := range listOfUrls {
          go f(myurl, &wg)
        }
    wg.Wait()
}

func f(myurl string, wg *sync.WaitGroup) {
    body := getUrlBody(myurl)
    fmt.Println(len(body))
    wg.Done()
 }

所有goroutine都共享一个
myurl
变量。有关更多信息,请参阅

将代码更改为:

func f(listOfUrls []string){
  var wg sync.WaitGroup
  wg.Add(len(listOfUrl))
  for _, myurl := range(listOfUrls){
    go func(myurl string){
           body := getUrlBody(myurl)
           fmt.Println(len(body))
           wg.Done()
       }(myurl)    
  } 
  wg.Wait()
}


您在
myurl
上的代码中有一个竞争条件。您应该通过将其传递给闭包来复制它。否则,它可能主要引用所有goroutine中您范围内的最后一个元素。是的,我添加了第二个版本,我猜是正确的,但也不起作用。当运行第二个版本时会发生什么?如果ListoForls有4个url,它会从GetBodyURL打印四次(“获取url:”),然后它会打印四次长度的零。。。理论上,它应该从getBodyUrls打印“Done url:”,并打印正确的大小…不可能对正在发生的事情进行评论,因为您的评论中提到的打印语句都不在您显示的代码中。谢谢。请问,如果我的编辑加上开始主题,有意义吗?
func f(listOfUrls []string){
  var wg sync.WaitGroup
  wg.Add(len(listOfUrl))
  for _, myurl := range(listOfUrls){
    myurl := myurl
    go func(){
           body := getUrlBody(myurl)
           fmt.Println(len(body))
           wg.Done()
       }()    
  } 
  wg.Wait()
}