3 回答
TA贡献1877条经验 获得超1个赞
需要清除频道的内容是不寻常的。频道不提供此功能 - 但您可以制作一个以这种方式运行的 goroutine(...如果您真的想要的话)。
通常,您会更多地考虑在一个通道上输入并在另一个通道上输出的 goroutine;两个通道都携带相同的数据类型。原则上,您可以通过这种方式对所有缓冲通道进行建模;对于它的客户端,goroutine 的行为就像一个普通的缓冲通道,因为它传递它接收到的内容。
将第三个通道添加到 goroutine 中,并在它和输入之间进行选择。这将允许您触发缓冲区的清空,而不会出现竞争条件。简单。
现在有三个通道连接到 goroutine - 两个输入和一个输出。因此,当您设计将使用它的事物时,您可以推断刷新该数据的语义是什么。
一个亲戚浮现在脑海中。考虑一个具有一个输入和一个输出通道的 goroutine。它提供了一个固定大小的覆盖缓冲区,即一个总是准备好从其输入通道读取的缓冲区,即使输出通道被阻塞。这也需要一个默认情况下的选择,但不需要第三个通道。覆盖缓冲区有一个明确的用例:当通道和 goroutine 连接到循环中时,很可能发生死锁。覆盖缓冲区作为死锁的一种候选解决方案派上用场,因为有些数据在迟到时是无用的——例如,当应用程序太忙而无法响应它们时,您可以在 GUI 中丢弃鼠标事件。
TA贡献2037条经验 获得超6个赞
当我遇到这个问题时,我就是这样处理的。
func (s *ReadStream) drain() {
go func() {
for b := range s.chan {
blackhole(b)
}
}()
}
func blackhole(b []byte) {}
在您的选择可能被阻止的情况下 context.Context 似乎是错误的选择:
for {
select {
case <-ctx.Done():
return
default:
send<-getData()
}
}
如果发送已满,则在接收完成信号之前,我们会受到外部 goroutine 的支配。如果您确定消费者会在通道关闭之前阅读,这是可以的,但是如果这些消费者可能会遇到错误情况并返回,那么您所能做的就是希望。在这种特定情况下,我喜欢用内部退出 chan 和等待组替换上下文,然后提供公共 Kill() 方法。当然,只要我绝对确定我可以扔掉数据。
func (s *ReadStream) Kill() {
s.quit<-struct{}{}
s.drain() // ensure goroutine sees the cancel
s.wg.Wait() // wait for goroutine to see the cancel
s.close()
}
- 3 回答
- 0 关注
- 146 浏览
添加回答
举报