sync.WaitGroup不等待

huangapple go评论65阅读模式
英文:

sync.WaitGroup doesnt waits

问题

也许我没有看到明显的问题,我做错了什么:

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

如果我移除 wggo,我可以正确地接收到每个 URL 正文的大小。但是按照上面的方式,它几乎立即打印出零。getUrlBody() 有时需要执行几分钟。

回答评论:我也尝试了这种方式,为了确保,它表现出相同的行为。
我发现错误出现在 getUrlBodymain() 函数中...

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()
}
英文:

May be I can not see obvious thing, what am I doing wrong:

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()
}

If I remove wg and go, I receive the size of each url body correctly. If I do it as in above, it prints zeroes almost instantly. The getUrlBody() takes time to execute sometimes minutes.

Answering comment: I also tried it this way, to be sure, and it demonstrate same behaviour.
I found the error was in getUrlBody and main() function...

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()
 }

答案1

得分: 2

所有的goroutine都共享单个myurl变量。请参阅https://golang.org/doc/faq#closures_and_goroutines获取更多信息。

将代码更改为:

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()
}

或者

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()
}
英文:

All of the goroutines are sharing the single myurl variable. See https://golang.org/doc/faq#closures_and_goroutines for more information.

Change the code to:

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()
}

or

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()
}

huangapple
  • 本文由 发表于 2015年6月2日 01:39:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/30579752.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定