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

Jam*_*dge 16 go

我正在设计一个包,我希望根据观察者模式提供一个API:也就是说,有些点我想发出一个信号,触发零个或多个感兴趣的各方.那些感兴趣的人不一定需要了解彼此.

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

在我使用过的许多语言或框架中,有一些标准方法可以构建这些API,使它们按照用户期望的方式运行:例如g_signal_*基于glib的应用程序,事件和addEventListener()JavaScript DOM应用程序的功能,或者用于多播代理的多播代理.净.

Go有什么类似的吗?如果没有,是否有其他方法可以构建这种类型的API,这在Go中更为惯用?

zzz*_*zzz 15

我会说从频道接收的goroutine在某种程度上是观察者的类比.因此,在Go中公开事件的惯用方法是从包(函数)返回通道.另一个观察是在Go程序中不经常使用回调.其中一个原因是强者的存在select statement.

最后请注意:有些人(我也是)将GoF模式视为Go反模式.

  • 通道在相等性方面具有可比性,它们是一流的对象.要取消订阅,只需将频道传回发布者,它就可以找到频道的记录并采取适当的措施终止订阅. (5认同)
  • 我认为这个答案涵盖了一些用例,但我肯定希望听到更多有关此问题的意见/答案.频道给呼叫者("观察者")带来了更多的负担,因为它必须启动等待此频道的goroutine.如果相同的功能可以处理许多"事件",这可能变得很麻烦.作为反例,HTTP /处理程序的net/http中使用了回调.有一些用例,他们更有意义恕我直言. (2认同)

Dus*_*tin 5

我在几个项目中需要一个“观察者模式”类型的东西。 这是最近项目中的一个可重用示例。

它有一个相应的测试来展示如何使用它。

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

当你完成后,你Unregister.

它并不适合所有情况(例如,我可能想要为缓慢的观察者强制取消注册类型的事件),但它在我使用它的地方有效。