英文:
How can one close a channel in a defer block safely?
问题
考虑以下示例:
package main
import (
"fmt"
"time"
)
func main() {
ticker := time.NewTicker(2 * time.Second)
done := make(chan bool)
defer func() {
fmt.Println("exiting..")
done <- true
close(done)
}()
go func(ticker *time.Ticker, done chan bool) {
for {
select {
case <-done:
fmt.Println("DONE!")
break
case <-ticker.C:
fmt.Println("TICK!...")
}
}
}(ticker, done)
time.Sleep(7 * time.Second)
}
等待从done
接收的goroutine永远不会接收到消息,我猜测是因为主goroutine在之前就已经结束了。然而,如果我将主goroutine的睡眠时间更改为8秒钟,它会接收到一条消息。为什么睡眠时间会对此有影响?
这是因为有一个一秒钟的差异,它使得goroutine保持活动状态,而没有足够的时间来终止它。
要如何优雅地终止goroutine呢?
英文:
Consider the following example:
package main
import (
"fmt"
"time"
)
func main() {
ticker := time.NewTicker(2 * time.Second)
done := make(chan bool)
defer func() {
fmt.Println("exiting..")
done <- true
close(done)
}()
go func(ticker *time.Ticker, done chan bool) {
for {
select {
case <-done:
fmt.Println("DONE!")
break
case <-ticker.C:
fmt.Println("TICK!...")
}
}
}(ticker, done)
time.Sleep(7 * time.Second)
}
The goroutine waiting to receive from done
never receives as (I am guessing) the main goroutine finished beforehand. However if I change the sleep time of the main goroutine to 8 seconds it receives a message; Why is there this dependency on the sleep time?
Is it because there is that second difference that keeps the goroutine alive and the there isn't enough time to kill it?
How would I than kill the goroutine gracefully?
答案1
得分: 0
你需要确保在goroutine完成之前,main函数不会返回。最简单的方法是使用WaitGroup:
var wg sync.WaitGroup
defer wg.Wait()
wg.Add(1)
go func() {
defer wg.Done()
// ...
请注意,defer
语句按照相反的顺序执行,所以你必须将defer wg.Wait()
放在defer close(done)
之前,否则会发生死锁。
英文:
You need to ensure that main does not return before the goroutine finishes.
The simplest way to do this is using a WaitGroup:
var wg sync.WaitGroup
defer wg.Wait()
wg.Add(1)
go func() {
defer wg.Done()
// …
Note that defer
s run in reverse order, so you must put defer wg.Wait()
before defer close(done)
, otherwise it will deadlock.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论