Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Go中是否有设计信号或事件API的首选方法?_Go - Fatal编程技术网

在Go中是否有设计信号或事件API的首选方法?

在Go中是否有设计信号或事件API的首选方法?,go,Go,我正在设计一个包,其中我希望提供一个基于观察者模式的API:也就是说,我希望在某些点发出一个信号,该信号将触发零个或更多感兴趣的方。这些相关方不一定需要相互了解 我知道我可以从头开始实现这样的API(例如,使用一组通道或回调函数),但我想知道是否有一种构造此类API的首选方法 在我使用过的许多语言或框架中,都有标准的方法来构建这些API,以便它们按照用户期望的方式运行:例如,用于基于glib的应用程序的g\u signal.*函数,用于JavaScript DOM应用程序的事件和addEvent

我正在设计一个包,其中我希望提供一个基于观察者模式的API:也就是说,我希望在某些点发出一个信号,该信号将触发零个或更多感兴趣的方。这些相关方不一定需要相互了解

我知道我可以从头开始实现这样的API(例如,使用一组通道或回调函数),但我想知道是否有一种构造此类API的首选方法

在我使用过的许多语言或框架中,都有标准的方法来构建这些API,以便它们按照用户期望的方式运行:例如,用于基于glib的应用程序的
g\u signal.*
函数,用于JavaScript DOM应用程序的事件和
addEventListener()
,或用于.NET的多播委托


围棋有类似的吗?如果没有,是否有其他方法来构造这种类型的API,使其在Go中更为惯用?

我想说,从通道接收的goroutine在某种程度上是观测者的模拟。因此,在Go中公开事件的惯用方法是IMHO从包(函数)返回通道。另一个观察结果是,回调在Go程序中使用得不太频繁。其中一个原因也是强者的存在


最后,请注意:有些人(我也是)认为GOF模式是反模式。

GO给了你很多设计信号API的工具。

首先,你必须决定几件事:

你想要推式还是拉式的?发布者是向订阅者推送事件还是订阅者从发布者拉取事件


如果您想要一个推送系统,那么让订阅者给发布者一个发送消息的通道将非常有效。如果您想要一个pull方法,那么只需要一个由互斥锁保护的消息框就可以了。除此之外,如果不了解您的需求,就很难给出更多的细节。

我想说,没有标准的方法可以做到这一点,因为频道是内置在语言中的。没有通道库,没有标准的通道处理方法,只有通道。将通道作为内置的一流对象使您无需使用标准技术,并且可以以最简单、最自然的方式解决问题。

我在几个项目中需要一种“观察者模式”类型的东西。来自最近的一个项目

它有一个相应的测试,显示如何使用它

基本理论是,每当发生有趣的事情时,事件发射器都会使用一些数据调用
Submit
。任何想要知道该事件的客户端都将注册一个它从中读取事件数据的通道。您注册的此频道可以在
select
循环中使用,也可以直接读取(或缓冲并轮询)

完成后,您可以
取消注册


它并非适用于所有情况(例如,我可能需要一个针对慢速观察者的强制取消注册类型的事件),但它在我使用它的地方工作。

目前有一个基本的Golang版本的Node EventEmitter


请参见

我认为这个答案涵盖了一些用例,但我肯定希望听到更多关于这个问题的意见/答案。通道给调用者(“观察者”)增加了一点负担,因为它必须启动一个在该通道上等待的goroutine。如果同一个函数可以处理许多“事件”,这可能会变得很麻烦。作为反例,回调在net/http中用于http处理程序。我只使用了术语“观察者模式”,因为这是一个人们可能理解的术语:我不会通过首先将程序分解为命名的设计模式来编写程序,如果这是您想要了解的话。就您的API建议而言,我可以看到返回读取端通道的函数如何适用于订阅端,但您将如何对匹配的取消订阅API进行建模?通道在平等性方面具有可比性,它们是一流的对象。要取消订阅,只需将频道传递回发布者,它就可以找到频道的记录并采取适当的措施终止订阅。对于我的特定用例,发布者将广播事件,而订阅者将尽快作出反应。在这种情况下,互动性比吞吐量更重要,如果你是这么问的话。我知道频道(我甚至在问题中提到了它们)。但通道实际上只提供1-1通信机制,而我想要1-many(其中many可能为零)。所以我真的不能制作API通道,什么都不能做。一点也不正确。通道可以有多个发送方和多个接收方。无论如何,您可能会抱怨变量不好,因为它们一次只能保存一个值。需要更多吗?使用数据结构。发布者可以将其所有订阅者存储在一个片段、一个地图、一个树结构中,无论在您的案例中有什么意义。要发布,请迭代数据结构并将更新发送给每个订阅者。我将通道称为1-1,因为对于每条消息,通道将一个发送者连接到一个接收者。虽然您当然可以使用多个接收器,例如在goroutine之间分配工作,但这显然不是我要问的。