3 回答
TA貢獻1797條經驗 獲得超6個贊
這取決于您的程序,但一般來說我傾向于說不(您不需要在關閉頻道之前清除頻道):如果您關閉頻道時頻道中有項目,任何仍在從頻道閱讀的讀者都會接收項目,直到通道為空。
下面是一個例子:
package main
import (
"sync"
"time"
)
func main() {
var ch = make(chan int, 5)
var wg sync.WaitGroup
wg.Add(1)
for range make([]struct{}, 2) {
go func() {
for i := range ch {
wg.Wait()
println(i)
}
}()
}
for i := 0; i < 5; i++ {
ch <- i
}
close(ch)
wg.Done()
time.Sleep(1 * time.Second)
}
在這里,程序將輸出所有項目,盡管通道在任何讀者甚至可以從通道讀取之前嚴格關閉。
TA貢獻1784條經驗 獲得超7個贊
有更好的方法來實現您想要實現的目標。您當前的方法只會導致丟棄一些記錄,并隨機處理其他記錄(因為排水循環正在與所有消費者競爭)。這并沒有真正解決目標。
你想要的是取消。這是Go 并發模式中的一個示例:管道和取消
func sq(done <-chan struct{}, in <-chan int) <-chan int {
out := make(chan int)
go func() {
defer close(out)
for n := range in {
select {
case out <- n * n:
case <-done:
return
}
}
}()
return out
}
您將一個done通道傳遞給所有 goroutine,并在您希望它們都停止處理時關閉它。如果你經常這樣做,你可能會發現這個golang.org/x/net/context包很有用,它正式化了這個模式,并添加了一些額外的功能(比如超時)。
TA貢獻1815條經驗 獲得超10個贊
我覺得所提供的答案實際上并沒有澄清,除了不需要排水也不需要關閉的提示。因此,針對所描述的上下文的以下解決方案對我來說看起來很干凈,它終止了工作人員并刪除了對他們或相關頻道的所有引用,因此,讓 GC 清理頻道及其內容:
type worker struct {
submitted chan Task
stop chan bool
p *Processor
}
// executed in a goroutine
func (w *worker) run() {
for {
select {
case task := <-w.submitted:
if err := task.Execute(w.p); err != nil {
logger.Error(err.Error())
}
case <-w.stop:
logger.Warn("Worker stopped")
return
}
}
}
func (p *Processor) Stop() {
if atomic.CompareAndSwapInt32(&p.status, running, stopped) {
for _, w := range p.workers {
w.stop <- true
}
// GC all workers as soon as goroutines stop
p.workers = nil
// GC all published data when workers terminate
p.submitted = nil
// no need to do the following above:
// close(p.submitted)
// for range p.submitted {}
}
}
- 3 回答
- 0 關注
- 171 瀏覽
添加回答
舉報
