等待一个例程完成的正确方法

时间:2014-09-21 00:08:58

标签: go channel goroutine

我想知道在退出程序之前等待程序完成的正确方法是什么。阅读其他一些答案似乎bool chan可以解决问题,如Playground link

func do_stuff(done chan bool) {
    fmt.Println("Doing stuff")
    done <- true
}

func main() {
    fmt.Println("Main")
    done := make(chan bool)
    go do_stuff(done)
    <-done
    //<-done
}

我在这里有两个问题:

  • &lt; - 完成的原因是什么?

  • 如果我取消注释最后一行会怎样?我有一个死锁错误。这是因为频道是空的,没有其他功能向它发送值吗?

2 个答案:

答案 0 :(得分:5)

为什么<- done可以使用?

  • 它的工作原理是因为运行时检测到你正在向其他地方的某个频道写一些内容。

如果我取消注释最后一行会怎样?

  • 运行时很聪明,知道没有其他任何东西被写入并且死锁。

奖励,如果你对内存的限制非常有限,你可以使用done := make(chan struct{})done <- struct{}{}struct{}保证使用0内存。

答案 1 :(得分:5)

收听频道<- done是阻止操作,因此您的程序将不会继续发送,直到发送真或假,即done <- true

根据具体情况,您的问题可以有几个不同的答案。

例如,假设您想要并行化一系列需要很长时间的函数调用。

我会将sync包用于此

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            longOp()
            wg.Done()
        }()
    }
    // will wait until wg.Done is called 10 times
    // since we made wg.Add(1) call 10 times
    wg.Wait()
}

func longOp() {
    time.Sleep(time.Second * 2)
    fmt.Println("long op done")
}