2016-10-06 1 views
2

у меня есть следующий идти-код:Go ждать goroutines но делать такие вещи, в то же время

func execTask(input int, results chan<- int) { 
    //do stuff (in my case, start process and return something) 
    results <- someResult 
} 

func main() { 
    results := make(chan int) 

    for _, task := range tasks { 
     go execTask(task, results) 
    } 

    for result := range results { 
     fmt.Println(result) 
    } 
} 

Для линии for result := range results { я получаю ошибку: fatal error: all goroutines are asleep - deadlock!. В подпрограмме execTask я фактически выполняю процесс с os/exec, поэтому я не знаю, сколько результатов есть в results. Поэтому я должен ждать завершения всех моих процессов, но тем временем что-то делать с результатами. Когда все процессы завершаются, моя go-Programm также может быть прервана.

Как это сделать?

Спасибо, Lars

+0

результатов: = сделать (чан INT) для _ задачи: = задача диапазона { идет execTask (задачи, результаты) } Задача также призывают результаты, которые могут привести к тупиковой ситуации .. – MarmiK

ответ

5

Вы получаете ошибку тупиковой, потому что вы не закрываете results канала. Следовательно, main продолжает ждать дополнительных данных по results даже после того, как все execTask завершено, и ничего не нужно писать до results.

Вы можете исправить это с помощью sync.WaitGroup:

func main() { 
    var wg sync.WaitGroup 
    results := make(chan int) 

    wg.Add(len(tasks)) 
    for _, task := range tasks { 
     go func(task int) { 
      defer wg.Done() 
      execTask(task, results) 
     }(task) 
    } 

    go func() { 
     wg.Wait() // wait for each execTask to return 
     close(results) // then close the results channel 
    } 

    for result := range results { 
     fmt.Println(result) 
    } 
} 

Что касается работы на execTask результатов в то время как другие процессы по-прежнему выполняется, у вас уже есть правильная идея. Просто работайте над ними в цикле results. Убейте еще несколько goroutines там, если вы хотите больше одновременных исполнений.

+3

Не используй 'task' из диапазона вашего закрытия. Сделайте свое закрытие «task int» и передайте его: см. Https://github.com/golang/go/wiki/CommonMistakes#using-goroutines-on-loop-iterator-variables – jcbwlkr

+0

исправлено .. спасибо .. – abhink

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