我刚刚开始使用并发。我有其他语言的并发经验,如果你想写一个封闭的频道,我会感到非常难过。
这种模式非常有用,因为你可以解耦actor的生命周期并使它们独立。这使您无需同步清理它们。基本上我可以让读者在关闭之前关闭通道,并通知任意数量的写入器并通过通道上的写入错误停止阻塞(取消)。
因此,我编写了一个通用函数来处理这种形式的消息传递:/// Sends a message to a remote general channel.
/// Returns true if the message was sent (the send stopped blocking) or false if
/// the sender closed the channel.
/// When the channel is unbuffered, this function returning true means that the
/// sender has received the message and is acting on it.
func SendRemoteCmd(ch chan interface{}, msg interface{}) bool {
defer func() {
recover()
}()
ch <- msg
return true
}
效果很好,我只是害怕golang开发者会生气,打电话给我,告诉我他们在阅读这段代码时会“找到我”。也许有一些很好的理由说明语言之神首先决定这应该是恐慌。如果是这种情况,你建议用什么设计?
答案 0 :(得分:2)
由于发送到关闭频道是一个程序错误,您的频道发送到可以关闭的频道必须同步。一般来说,正确的模式是在尝试发送之前获得某种锁定,如果该频道可以被第三方关闭。
在您尝试发送可以关闭的频道之前,这并不是特别有趣,因为select
语句的一部分涉及其他可能的操作。在这种情况下,一个常见的模式是将频道设置为nil
,如果对它们的操作不应该,或者不能进行。我在torrent客户端here的connection.writeOptimizer
函数中有一个非常复杂的例子。
请注意,示例中仔细考虑了写入管道中涉及的资源的所有权,这是一种防止问题的好方法,例如关闭渠道。 writeOptimizer
有效地拥有connection.writeCh
,并通过关闭它向下游发出信号,表示没有其他数据到来。它也是发送到该例程的唯一goroutine,从而避免了必须通过其他方式将写入与通道关闭同步。