2015-06-01 58 views
-1

可能是我看不到明顯的事情,我在做什麼錯:sync.WaitGroup犯規等待

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

你在你的代碼中的競爭危害的'myurl'。您應該將其複製傳遞給閉包。否則,它可能主要是指你所有goroutine中範圍內的最後一個元素。 – inf

+0

是的,我添加了第二個版本,我猜對了,但不起作用。 – MikeKlemin

+0

當你運行第二個版本時會發生什麼? –

回答

2

所有夠程的共享單一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() 
} 
+0

謝謝。 ,如果我的編輯除了開始話題,是否有意義? – MikeKlemin