英文:
Is there a preferred way to design signal or event APIs in Go?
问题
我正在设计一个包,我想基于观察者模式提供一个API:也就是说,有一些地方我想发出一个信号,这个信号将触发零个或多个感兴趣的方。这些感兴趣的方不一定需要知道彼此。
我知道我可以从头开始实现这样的API(例如使用一组通道或回调函数),但我想知道是否有一种首选的方式来构建这样的API。
在我使用过的许多语言或框架中,都有标准的方法来构建这些API,以使它们的行为符合用户的期望:例如,用于glib应用程序的g_signal_*
函数,用于JavaScript DOM应用程序的事件和addEventListener()
,或者用于.NET的多播委托。
Go语言中是否有类似的东西?如果没有,是否有其他更符合Go语言习惯的方式来构建这种类型的API?
英文:
I am designing a package where I want to provide an API based on the observer pattern: that is, there are points where I'd like to emit a signal that will trigger zero or more interested parties. Those interested parties shouldn't necessarily need to know about each other.
I know I can implement an API like this from scratch (e.g. using a collection of channels or callback functions), but was wondering if there was a preferred way of structuring such APIs.
In many of the languages or frameworks I've played with, there has been standard ways to build these APIs so that they behave the way users expect: e.g. the g_signal_*
functions for glib based applications, events and addEventListener()
for JavaScript DOM apps, or multicast delegates for .NET.
Is there anything similar for Go? If not, is there some other way of structuring this type of API that is more idiomatic in Go?
答案1
得分: 15
我会说,一个从通道接收的goroutine在某种程度上类似于观察者。在Go中,一种惯用的暴露事件的方式是从包(函数)返回通道。另一个观察是,在Go程序中回调函数并不经常使用。其中一个原因也是因为强大的select语句
的存在。
最后一点说明:一些人(包括我)认为GoF模式是Go反模式。
英文:
I would say that a goroutine receiving from a channel is an analogue of an observer to a certain extent. An idiomatic way to expose events in Go would be thus IMHO to return channels from a package (function). Another observation is that callbacks are not used too often in Go programs. One of the reasons is also the existence of the powerful select statement
.
As a final note: some people (me too) consider GoF patterns as Go antipatterns.
答案2
得分: 5
我在几个项目中需要一个“观察者模式”类型的东西。这里是一个可重用的示例,来自最近的一个项目。
它有一个相应的测试,展示了如何使用它。
基本理论是,事件发射器在发生有趣的事情时调用Submit
,并传递一些数据。任何想要了解该事件的客户端都会Register
一个通道,用于读取事件数据。你注册的这个通道可以在select
循环中使用,或者直接读取它(或者缓冲并轮询它)。
当你完成时,你可以Unregister
。
它并不适用于所有情况(例如,我可能希望有一个用于慢观察者的强制取消注册类型的事件),但在我使用它的地方它是有效的。
英文:
I needed an "observer pattern" type thing in a couple of projects. Here's a reusable example from a recent project.
It's got a corresponding test that shows how to use it.
The basic theory is that an event emitter calls Submit
with some piece of data whenever something interesting occurs. Any client that wants to be aware of that event will Register
a channel it reads the event data off of. This channel you registered can be used in a select
loop, or you can read it directly (or buffer and poll it).
When you're done, you Unregister
.
It's not perfect for all cases (e.g. I may want a force-unregister type of event for slow observers), but it works where I use it.
答案3
得分: 4
Go为设计信号API提供了许多工具。
首先,您需要决定一些事情:
您想要推送模型还是拉取模型?例如,发布者是否向订阅者推送事件,还是订阅者从发布者拉取事件?
如果您想要一个推送系统,那么让订阅者给发布者提供一个通道来发送消息将非常有效。如果您想要一个拉取方法,那么只需要一个由互斥锁保护的消息盒子即可。除此之外,如果不了解更多关于您的要求,很难提供更多细节。
英文:
Go gives you a lot of tools for designing a signal api.
First you have to decide a few things:
Do you want a push or a pull model? eg. Does the publisher push events to the subscribers or do the subscribers pull events from the publisher?
If you want a push system then having the subscribers give the publisher a channel to send messages on would work really well. If you want a pull method then just a message box guarded with a mutex would work. Other than that without knowing more about your requirements it's hard to give much more detail.
答案4
得分: 2
我会说没有标准的方法来做这个,因为通道已经内置到语言中了。没有通道库提供通道的标准操作方式,只有通道本身。将通道作为内置的一等对象,使你不必使用标准技术,可以以最简单、最自然的方式解决问题。
英文:
I would say there is no standard way of doing this because channels are built into the language. There is no channel library with standard ways of doing things with channels, there are simply channels. Having channels as built in first class objects frees you from having to work with standard techniques and lets you solve problems in the simplest most natural way.
答案5
得分: 0
这里有一个基于Golang的Node EventEmitter的基本版本,可以在https://github.com/chuckpreslar/emission找到。
请参阅http://itjumpstart.wordpress.com/2014/11/21/eventemitter-in-go/
英文:
There is a basic Golang version of Node EventEmitter at https://github.com/chuckpreslar/emission
See http://itjumpstart.wordpress.com/2014/11/21/eventemitter-in-go/
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论