> In your approach, I'd need to centralize reads from the Listener.Notify channel, and dispatch to the right processing code according to the message payload myself, no? This becomes more difficult if I need to add/remove listeners dynamically, because whatever is draining the Listener.Notify queue will need to, e.g., accept callbacks for what to do for each type of message if I don't want to hardcode the full set of possibilities up front.
> Or is there a better way to do that? How do you envisage dynamic listen/notify?

What I had in mind is having another object, say, ListenDispatcher build on top of Listen which returns a channel from a call to Listen(). That (Go) channel would then get one item sent to it for every notification that is sent on the notification channel.  The dispatcher would maintain the channels in a map somewhere and Listen/Unlisten the underlying Listener accordingly.  I believe this is the nicest interface you could get in the end.

I originally wanted to include this in this patch, but it got way too complex to include from the get-go.  So now I've been trying to build the most basic, reusable building blocks for people to build the perfect tools for themselves.  Though now we're at the point where we might want to reconsider including some implementation of this "dispatcher" with this feature, because I think people would eventually want something like that anyway, and they would have to reinvent the wheel every time.