我正在设计一个包,我希望根据观察者模式提供一个API:也就是说,有些地方我想发出一个信号,触发零个或多个感兴趣的人。那些感兴趣的人不一定需要了解彼此。
我知道我可以从头开始实现这样的API(例如使用一组通道或回调函数),但是想知道是否有一种构建这种API的首选方法。
在我使用过的许多语言或框架中,有一些标准方法可以构建这些API,使它们的行为符合用户的期望:例如:基于glib的应用程序的g_signal_*
函数,JavaScript DOM应用程序的事件和addEventListener()
,或.NET的多播委托。
Go有什么相似之处吗?如果没有,是否有其他方法可以构建这种类型的API,这在Go中更为惯用?
答案 0 :(得分:15)
我想说从频道接收的goroutine在某种程度上是观察者的类比。因此,在Go中公开事件的惯用方法是从包(函数)返回通道。另一个观察是在Go程序中不经常使用回调。其中一个原因是强大的select statement
的存在。
最后请注意:有些人(我也是)将GoF模式视为Go反模式。
答案 1 :(得分:4)
Go为您提供了许多设计信号api的工具。
首先,你必须做出一些决定:
您想要推模型还是拉模型?例如。发布者是否将事件推送给订阅者,或者订阅者是否从发布者处提取事件?
如果你想要一个推送系统,那么让订阅者给发布者一个发送消息的频道就可以了。如果你想要一个pull方法,那么只需一个用互斥锁保护的消息框就行了。除此之外,如果不了解您的要求,很难提供更多详细信息。
答案 2 :(得分:3)
我需要在几个项目中使用“观察者模式”类型的东西。 Here's a reusable example来自最近的一个项目。
它有一个相应的测试,显示如何使用它。
基本理论是,只要有趣的事情发生,事件发射器就会用Submit
调用一些数据。任何想要了解该事件的客户都将Register
一个从其读取事件数据的频道。您注册的此频道可以在select
循环中使用,也可以直接读取(或缓冲并轮询)。
完成后,您Unregister
。
对于所有案例来说,它并不完美(例如,对于慢速观察者,我可能需要强制取消注册类型的事件),但它在我使用它的地方有效。
答案 3 :(得分:1)
我想说没有标准的方法可以做到这一点,因为频道是内置于语言中的。没有频道库,有标准的频道处理方式,只有频道。将通道作为第一类对象构建,使您不必使用标准技术,并以最简单最自然的方式解决问题。
答案 4 :(得分:0)
https://github.com/chuckpreslar/emission
有一个基本的Golang版本的Node EventEmitter请参阅http://itjumpstart.wordpress.com/2014/11/21/eventemitter-in-go/