去等goroutines,但同时做的东西

Lar*_*ker 2 concurrency go goroutine

我有以下go-Code:

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

对于这行,for result := range results {我得到一个错误: fatal error: all goroutines are asleep - deadlock!.在例程中execTask我实际上用os/exec执行一个进程,所以我不知道有多少结果results.所以我必须等待所有进程的完成,但同时对结果做一些事情.当所有进程终止时,我的go-Programm也可能被终止.

我该怎么做呢?

谢谢,拉尔斯

abh*_*ink 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

至于execTask在其他进程仍在执行时处理结果,您已经有了正确的想法.只需在results范围循环中处理它们.如果你想要更多的并发执行,可以在那里启动一些goroutine.

  • 不要像你那样使用封闭范围内的`task`.让你的闭包接受`task int`并传入它:参见https://github.com/golang/go/wiki/CommonMistakes#using-goroutines-on-loop-iterator-variables (3认同)