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

met*_*eto 3 channel go goroutine

我想知道在退出程序之前等待程序完成的正确方法是什么.阅读其他一些答案似乎bool chan会做到这一点,就像Playground链接一样

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

我这里有两个问题:

  • 为什么< - 完成工作?

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

jma*_*ney 6

听通道<- done,是一个阻塞操作,所以你的程序将不会继续,直到发送true或false,即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")
}
Run Code Online (Sandbox Code Playgroud)


One*_*One 5

为什么要<- done工作?

  • 它的工作原理是因为运行时检测到您正在向其他地方的通道写入内容.

如果我取消注释最后一行会发生什么?

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

奖金,如果你非常的内存的限制,您可以使用done := make(chan struct{})done <- struct{}{},struct{}是保证使用0内存.