// Package goemitter package goemitter import ( "sync" ) type EventEmitter struct { callbacks map[string]map[int]func(args ...interface{}) onceCallbacks map[string][]func(args ...interface{}) lock sync.Mutex counter int } type EventHandle struct { id int event string emitter *EventEmitter } func (eh *EventHandle) Remove() { eh.emitter.lock.Lock() defer eh.emitter.lock.Unlock() if _, ok := eh.emitter.callbacks[eh.event]; ok { delete(eh.emitter.callbacks[eh.event], eh.id) } } func (e *EventEmitter) On(event string, callback func(args ...interface{})) *EventHandle { e.lock.Lock() defer e.lock.Unlock() e.counter++ if _, ok := e.callbacks[event]; !ok { e.callbacks[event] = make(map[int]func(args ...interface{})) } e.callbacks[event][e.counter] = callback return &EventHandle{ id: e.counter, event: event, emitter: e, } } func (e *EventEmitter) Once(event string, callback func(args ...interface{})) { e.lock.Lock() defer e.lock.Unlock() if _, ok := e.onceCallbacks[event]; !ok { e.onceCallbacks[event] = []func(args ...interface{}){callback} } else { e.onceCallbacks[event] = append(e.onceCallbacks[event], callback) } } func (e *EventEmitter) Emit(event string, data ...interface{}) { e.lock.Lock() defer e.lock.Unlock() if callbacks, ok := e.callbacks[event]; ok { for _, callback := range callbacks { go callback(data...) } } if onceCallbacks, ok := e.onceCallbacks[event]; ok { for _, callback := range onceCallbacks { go callback(data...) } e.onceCallbacks[event] = []func(args ...interface{}){} } } func (e *EventEmitter) EmitSync(event string, data ...interface{}) { e.lock.Lock() defer e.lock.Unlock() if callbacks, ok := e.callbacks[event]; ok { for _, callback := range callbacks { callback(data...) } } if onceCallbacks, ok := e.onceCallbacks[event]; ok { for _, callback := range onceCallbacks { callback(data...) } e.onceCallbacks[event] = []func(args ...interface{}){} } } func NewEmitter() *EventEmitter { ret := &EventEmitter{} ret.callbacks = make(map[string]map[int]func(args ...interface{})) ret.onceCallbacks = make(map[string][]func(args ...interface{})) return ret }