首页 > 解决方案 > 谁应该分配频道,被叫方的主叫方?

问题描述

我正在尝试用 Go 设计一个简单的家庭自动化程序。当状态改变时,我的灯泡会返回消息流。这可以通过回调来处理,或者在 Go 中使用通道可能会更好。

通过回调,很明显灯泡 API 的调用者实现了特定的函数签名并将函数传递给库。当灯泡改变状态或发生通信错误时,将调用该函数。当客户端不再对更新感兴趣时,库将分配一个要调用的完成函数。例如

 type DeviceUpdate = func(Device, error)
 type Done = func()

 func (client *Client) ObserveDevice(deviceID int, deviceUpdate DeviceUpdate) (Done, error) {

在我的情况下,通道似乎呈现出更好的抽象,因为它们可以轻松合并,可以添加缓冲,可以轻松编织中间件等。我对上述声明的通道表示有点挣扎。对于这种情况,Go 中的正确约定是什么,即整个系统上的数据通道、错误通道和完成/关闭操作。

我在想通道应该由调用者分配,类似于函数。这样,调用者可以在激活整个设置之前正确地实例化通道并连接中间件。

func (client *Client) ObserveDevice(deviceID int, data chan Device, done chan struct{}, err chan error) error {

另一方面,让灯泡库分配通道对于消费者代码来说似乎要简单得多——您只需调用一个函数,无需分配 3 个通道。Go time 模块似乎也勇敢地走这条路,例如https://golang.org/pkg/time/#After

在我的情况下,让库分配通道将导致如下签名

func (client *Client) ObserveDevice(deviceID int) (data chan Device, done chan struct{}, err chan error) {

那么通道分配的 Go 标准做法是什么?是调用者与被调用者还是生产者与消费者?

从网络流汇集更新时通常的做法是有 3 个通道 - 数据、错误和完成?

我在有关 Go 的通道和并发性的文章和视频中进行了一些挖掘,但找不到(可能是由于懒惰)记录的最佳实践。我假设示例中隐含了分配通道的调用者。见https://gobyexample.com/closing-channelshttps://blog.golang.org/pipelines

标签: godesign-patternsconcurrencyobserverschannels

解决方案


推荐阅读