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

时间:2012-12-18 07:14:06

标签: go

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

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

在我使用过的许多语言或框架中,有一些标准方法可以构建这些API,使它们的行为符合用户的期望:例如:基于glib的应用程序的g_signal_*函数,JavaScript DOM应用程序的事件和addEventListener(),或.NET的多播委托。

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

5 个答案:

答案 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)