2015-06-01 4 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() 
} 

Если удалить РГ и идти, я получаю размер каждого тела URL-адрес правильно. Если я делаю это так, как описано выше, он почти мгновенно печатает нули. GetUrlBody() требует времени для выполнения иногда минут.

Ответ на вопрос: Я также пробовал это таким образом, чтобы быть уверенным, и он демонстрирует такое же поведение. я обнаружил, что ошибка была в getUrlBody и функции главного() ...

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'. Вы должны скопировать его, передав его закрытию. В противном случае это, вероятно, будет главным образом относиться к последнему элементу вашего диапазона во всех ваших goroutines. – inf

+0

Да, я добавил вторую версию, которая, я думаю, правильная, но не работает. – MikeKlemin

+0

Что происходит, когда вы запускаете вторую версию? –

ответ

2

Все goroutines разделяют единую 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

Смежные вопросы