【发布时间】:2015-07-18 10:31:44
【问题描述】:
我正在开发我的第一个真正的 Go 项目,一个消息传递 API。我使用通道在用户 goroutine 和使用线程不安全、基于事件的 C 协议库的库 goroutine 之间传递消息和其他数据。详情https://github.com/apache/qpid-proton/blob/master/proton-c/bindings/go/README.md
我的问题有两个相关的部分:
1.处理跨渠道错误的常见习语是什么?
一端的goroutine炸了,我如何确保另一端解除阻塞,得到error值并且以后不会再次被阻塞?
给读者:
- 我可以关闭频道,但没有错误信息。
- 我可以通过
struct { data, error } - 或使用第二个频道。
优点和缺点?其他想法?
对于作家:我不能不慌不忙地关闭,所以我想我需要第二个频道。这是惯用语吗?
select {
case sendChan <- data: sentOk()
case err := <- errChan: oops(err)
}
关闭后我也无法写入,因此我需要将错误存储在某处并在尝试写入之前检查。还有其他方法吗?
2。在 API 中公开通道。
我需要通道来传递错误信息:我应该将这些通道设为公共字段还是将它们隐藏在方法中?
有一个权衡,我没有经验来评估它:
暴露通道允许用户直接选择,但它要求他们正确实施错误处理模式(在写入之前检查错误,选择错误以及写入)。这似乎很复杂且容易出错,但可能是因为我没有经验。
在方法中隐藏通道可简化并强制正确使用库。但是现在异步用户必须创建自己的 goroutine 和通道。他们可能只是复制图书馆已经做的事情,这很愚蠢。路径上还有一个额外的 goroutine 和通道。也许这没什么大不了的,但数据通道是我的库的关键路径,我认为它必须与错误通道一起隐藏。
我可以做到这两点:为高级用户公开渠道和为有简单需求的人提供一个简单的方法包装器。这更值得支持,但如果任何一个都不能满足所有情况,那么它是值得的。
标准的 net.Conn 使用阻塞方法,而不是通道,我编写了 goroutine 将数据泵送到我的 C 事件循环通道,所以我知道它可以做到,但我并不觉得它微不足道。 net.Conn 将系统调用而不是通道封装在下面,因此“暴露通道”不是一种选择。是否有任何标准库导出带有错误处理的通道? (time.After不算,没有错误)
非常感谢! 艾伦
【问题讨论】:
标签: error-handling go channel