英文:
proper way of waiting for a go routine to finish
问题
我希望知道在退出程序之前等待一个go routine完成的正确方法。阅读其他答案,似乎使用一个bool类型的通道可以解决问题,就像这样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
}
我有两个问题:
-
为什么
<-done
能够正常工作? -
如果我取消注释最后一行会发生什么?我会得到一个死锁错误。这是因为通道是空的,没有其他函数向其发送值吗?
英文:
I wish to know what is the proper way of waiting for a go routine to finish before exiting the program. Reading some other answers it seems that a bool chan will do the trick, as in 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
}
I have two questions here:
-
why the <- done works at all?
-
what happens if I uncomment the last line? I have a deadlock error. Is this because the channel is empty and there is no other function sending values to it?
答案1
得分: 11
为什么<- done
会起作用?
- 这是因为运行时检测到你在其他地方向通道写入了数据。
如果我取消注释最后一行会发生什么?
- 运行时会聪明地知道没有其他数据被写入,从而导致死锁。
额外奖励,如果你的内存非常有限,你可以使用done := make(chan struct{})
和done <- struct{}{}
,struct{}
保证使用0内存。
英文:
Why the <- done
works at all?
- It works because the runtime detects that you're writing something to the channel somewhere else.
what happens if I uncomment the last line?
- The runtime is smart enough to know that there's nothing else being written and it deadlocks.
Bonus, if you're extremely limited on memory, you can use done := make(chan struct{})
and done <- struct{}{}
, struct{}
is guaranteed to use 0 memory.
答案2
得分: 11
监听通道<- 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()
}()
}
// 等待直到wg.Done被调用10次
// 因为我们调用了wg.Add(1) 10次
wg.Wait()
}
func longOp() {
time.Sleep(time.Second * 2)
fmt.Println("long op done")
}
以上是一个使用sync.WaitGroup
实现并行函数调用的示例代码。
英文:
Listening to channel <- done
, is a blocking operation, so your program won't continue until true or false is sent i.e. done <- true
.
Your question can have a few different answers depending on the circumstance.
For instance, suppose you wanted to parallelize a series of function calls that take a long time.
I would use the sync
package for this
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")
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论