sync.WaitGroup不等待

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

sync.WaitGroup doesnt waits

问题

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

  1. func printSize(listOfUrls []string) {
  2. var wg sync.WaitGroup
  3. wg.Add(len(listOfUrls))
  4. for _, myurl := range listOfUrls {
  5. go func() {
  6. body := getUrlBody(myurl)
  7. fmt.Println(len(body))
  8. wg.Done()
  9. }()
  10. }
  11. wg.Wait()
  12. }

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

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

  1. func printSize(listOfUrls []string) {
  2. var wg sync.WaitGroup
  3. wg.Add(len(listOfUrls))
  4. for _, myurl := range listOfUrls {
  5. go f(myurl, &wg)
  6. }
  7. wg.Wait()
  8. }
  9. func f(myurl string, wg *sync.WaitGroup) {
  10. body := getUrlBody(myurl)
  11. fmt.Println(len(body))
  12. wg.Done()
  13. }
英文:

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

  1. func printSize (listOfUrls []string){
  2. var wg sync.WaitGroup
  3. wg.Add(len(listOfUrl))
  4. for _, myurl := range(listOfUrls){
  5. go func(){
  6. body := getUrlBody(myurl)
  7. fmt.Println(len(body))
  8. wg.Done()
  9. }()
  10. }
  11. wg.Wait()
  12. }

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...

  1. func printSize(listOfUrls []string) {
  2. var wg sync.WaitGroup
  3. wg.Add(len(listOfUrls))
  4. for _, myurl := range listOfUrls {
  5. go f(myurl, &wg)
  6. }
  7. wg.Wait()
  8. }
  9. func f(myurl string, wg *sync.WaitGroup) {
  10. body := getUrlBody(myurl)
  11. fmt.Println(len(body))
  12. wg.Done()
  13. }

答案1

得分: 2

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

将代码更改为:

  1. func f(listOfUrls []string){
  2. var wg sync.WaitGroup
  3. wg.Add(len(listOfUrl))
  4. for _, myurl := range(listOfUrls){
  5. go func(myurl string){
  6. body := getUrlBody(myurl)
  7. fmt.Println(len(body))
  8. wg.Done()
  9. }(myurl)
  10. }
  11. wg.Wait()
  12. }

或者

  1. func f(listOfUrls []string){
  2. var wg sync.WaitGroup
  3. wg.Add(len(listOfUrl))
  4. for _, myurl := range(listOfUrls){
  5. myurl := myurl
  6. go func(){
  7. body := getUrlBody(myurl)
  8. fmt.Println(len(body))
  9. wg.Done()
  10. }()
  11. }
  12. wg.Wait()
  13. }
英文:

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:

  1. func f(listOfUrls []string){
  2. var wg sync.WaitGroup
  3. wg.Add(len(listOfUrl))
  4. for _, myurl := range(listOfUrls){
  5. go func(myurl string){
  6. body := getUrlBody(myurl)
  7. fmt.Println(len(body))
  8. wg.Done()
  9. }(myurl)
  10. }
  11. wg.Wait()
  12. }

or

  1. func f(listOfUrls []string){
  2. var wg sync.WaitGroup
  3. wg.Add(len(listOfUrl))
  4. for _, myurl := range(listOfUrls){
  5. myurl := myurl
  6. go func(){
  7. body := getUrlBody(myurl)
  8. fmt.Println(len(body))
  9. wg.Done()
  10. }()
  11. }
  12. wg.Wait()
  13. }

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:

确定