Skip to content

Instantly share code, notes, and snippets.

Last active January 1, 2016 16:17
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
Event dispatcher
package events
import (
type Event interface {
Clone() Event
type Dispatcher struct {
handlers map[reflect.Type][]reflect.Value
lock *sync.RWMutex
func NewDispatcher() *Dispatcher {
return &Dispatcher{
handlers: make(map[reflect.Type][]reflect.Value),
lock: &sync.RWMutex{},
// RegisterEvent registers custom events making it possible to register listeners for them.
// It has to be mentioned that in order to listen for the event it has to be registered firstly.
// It is REQUIRED to override Clone() method provided by anonymous struct BaseEvent,
// otherwise thesame copy will be sent to all listeners
func (d *Dispatcher) RegisterEvent(event Event) bool {
defer d.lock.Unlock()
typ := reflect.TypeOf(event).Elem()
if _, ok := d.handlers[typ]; ok {
return false
var chanArr []reflect.Value
d.handlers[typ] = chanArr
return true
// RegisterListener registers chanel accepting desired event - a listener.
// It is important to note that what channel accepts determines what will be sent to it.
// If listened event is not registered false is returned
// It's advised to use a buffered channel for the listener, otherwise events might be lost in action.
// Panics if pipe is not a channel
func (d *Dispatcher) RegisterListener(pipe interface{}) bool {
defer d.lock.Unlock()
channelValue := reflect.ValueOf(pipe)
channelType := channelValue.Type()
if channelType.Kind() != reflect.Chan {
panic("Trying to register a non-channel listener")
channelIn := channelType.Elem()
if arr, ok := d.handlers[channelIn]; ok {
d.handlers[channelIn] = append(arr, channelValue)
return true
return false
// Dispatch provides thread safe method to send event to all listeners
// Returns true if succeded and false if event was not registered
func (d *Dispatcher) Dispatch(event Event) bool {
defer d.lock.RUnlock()
eventType := reflect.TypeOf(event).Elem()
if listeners, ok := d.handlers[eventType]; ok {
for _, listener := range listeners {
return true
return false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment