├── .github └── workflows │ └── ci.yml ├── .gitignore ├── LICENSE ├── README.md ├── events.go ├── events_test.go ├── go.mod └── logo.jpg /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | branches: [master] 8 | 9 | jobs: 10 | 11 | test: 12 | name: Test 13 | runs-on: ubuntu-latest 14 | 15 | strategy: 16 | matrix: 17 | go_version: [1.17] 18 | steps: 19 | 20 | - name: Set up Go 1.x 21 | uses: actions/setup-go@v2 22 | with: 23 | go-version: ${{ matrix.go_version }} 24 | 25 | - name: Check out code into the Go module directory 26 | uses: actions/checkout@v2 27 | 28 | - name: Test 29 | run: go test -v ./... 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_STORE 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2022 Gerasimos Maropoulos 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
4 |

5 | 6 | [![build status](https://img.shields.io/github/actions/workflow/status/kataras/go-events/ci.yml?style=for-the-badge)](https://github.com/kataras/go-events/actions) [![chat](https://img.shields.io/gitter/room/events/community.svg?color=cc2b5e&logo=gitter&style=for-the-badge)](https://gitter.im/events/community) [![donate](https://img.shields.io/badge/support-Go--Events-blue.svg?style=for-the-badge&logo=paypal)](https://iris-go.com/donate) 7 |
8 | 9 | Simple EventEmmiter for Go Programming Language. Inspired by [Nodejs EventEmitter](https://nodejs.org/api/events.html). For **Generics** support please wait until go1.18 stable is released, until then switch to [dev branch](https://github.com/kataras/go-events/tree/dev) instead. 10 | 11 | Overview 12 | ------------ 13 | `New() EventEmmiter // New returns a new, empty, EventEmmiter` 14 | 15 | 16 | ```go 17 | // AddListener is an alias for .On(eventName, listener). 18 | AddListener(EventName, ...Listener) 19 | // Emit fires a particular event, 20 | // Synchronously calls each of the listeners registered for the event named 21 | // eventName, in the order they were registered, 22 | // passing the supplied arguments to each. 23 | Emit(EventName, ...interface{}) 24 | // EventNames returns an array listing the events for which the emitter has registered listeners. 25 | // The values in the array will be strings. 26 | EventNames() []EventName 27 | // GetMaxListeners returns the max listeners for this emmiter 28 | // see SetMaxListeners 29 | GetMaxListeners() int 30 | // ListenerCount returns the length of all registered listeners to a particular event 31 | ListenerCount(EventName) int 32 | // Listeners returns a copy of the array of listeners for the event named eventName. 33 | Listeners(EventName) []Listener 34 | // On registers a particular listener for an event, func receiver parameter(s) is/are optional 35 | On(EventName, ...Listener) 36 | // Once adds a one time listener function for the event named eventName. 37 | // The next time eventName is triggered, this listener is removed and then invoked. 38 | Once(EventName, ...Listener) 39 | // RemoveAllListeners removes all listeners, or those of the specified eventName. 40 | // Note that it will remove the event itself. 41 | // Returns an indicator if event and listeners were found before the remove. 42 | RemoveAllListeners(EventName) bool 43 | // Clear removes all events and all listeners, restores Events to an empty value 44 | Clear() 45 | // SetMaxListeners obviously this function allows the MaxListeners 46 | // to be decrease or increase. Set to zero for unlimited 47 | SetMaxListeners(int) 48 | // Len returns the length of all registered events 49 | Len() int 50 | ``` 51 | 52 | 53 | ```go 54 | import "github.com/kataras/go-events" 55 | 56 | // initialize a new EventEmmiter to use 57 | e := events.New() 58 | 59 | // register an event with name "my_event" and one listener 60 | e.On("my_event", func(payload ...interface{}) { 61 | message := payload[0].(string) 62 | print(message) // prints "this is my payload" 63 | }) 64 | 65 | // fire the 'my_event' event 66 | e.Emit("my_event", "this is my payload") 67 | 68 | ``` 69 | 70 | Default/global EventEmmiter 71 | ```go 72 | 73 | // register an event with name "my_event" and one listener to the global(package level) default EventEmmiter 74 | events.On("my_event", func(payload ...interface{}) { 75 | message := payload[0].(string) 76 | print(message) // prints "this is my payload" 77 | }) 78 | 79 | // fire the 'my_event' event 80 | events.Emit("my_event", "this is my payload") 81 | 82 | ``` 83 | 84 | Remove an event 85 | 86 | ```go 87 | 88 | events.On("my_event", func(payload ...interface{}) { 89 | // first listener... 90 | },func (payload ...interface{}){ 91 | // second listener... 92 | }) 93 | 94 | println(events.Len()) // prints 1 95 | println(events.ListenerCount("my_event")) // prints 2 96 | 97 | // Remove our event, when/if we don't need this or we want to clear all of its listeners 98 | events.RemoveAllListeners("my_event") 99 | 100 | println(events.Len()) // prints 0 101 | println(events.ListenerCount("my_event")) // prints 0 102 | 103 | 104 | ``` 105 | Installation 106 | ------------ 107 | 108 | The only requirement is the [Go Programming Language](https://golang.org/dl). 109 | 110 | ```bash 111 | $ go get -u github.com/kataras/go-events 112 | ``` 113 | 114 | 115 | FAQ 116 | ------------ 117 | 118 | Explore [these questions](https://github.com/kataras/go-events/issues?go-events=label%3Aquestion) or navigate to the [community chat][Chat]. 119 | 120 | Versioning 121 | ------------ 122 | 123 | Current: v0.0.3 124 | 125 | Read more about Semantic Versioning 2.0.0 126 | 127 | - http://semver.org/ 128 | - https://en.wikipedia.org/wiki/Software_versioning 129 | - https://wiki.debian.org/UpstreamGuide#Releases_and_Versions 130 | 131 | Contributing 132 | ------------ 133 | 134 | If you are interested in contributing to the go-events project, please prepare a PR. 135 | 136 | License 137 | ------------ 138 | 139 | This project is licensed under the MIT License. 140 | 141 | License can be found [here](LICENSE). 142 | -------------------------------------------------------------------------------- /events.go: -------------------------------------------------------------------------------- 1 | // Package events provides simple EventEmmiter support for Go Programming Language 2 | package events 3 | 4 | import ( 5 | "log" 6 | "reflect" 7 | "sync" 8 | "sync/atomic" 9 | ) 10 | 11 | const ( 12 | // Version current version number 13 | Version = "0.0.3" 14 | // DefaultMaxListeners is the number of max listeners per event 15 | // default EventEmitters will print a warning if more than x listeners are 16 | // added to it. This is a useful default which helps finding memory leaks. 17 | // Defaults to 0, which means unlimited 18 | DefaultMaxListeners = 0 19 | 20 | // EnableWarning prints a warning when trying to add an event which it's len is equal to the maxListeners 21 | // Defaults to false, which means it does not prints a warning 22 | EnableWarning = false 23 | ) 24 | 25 | type ( 26 | // EventName is just a type of string, it's the event name 27 | EventName string 28 | // Listener is the type of a Listener, it's a func which receives any,optional, arguments from the caller/emmiter 29 | Listener func(...interface{}) 30 | // Events the type for registered listeners, it's just a map[string][]func(...interface{}) 31 | Events map[EventName][]Listener 32 | 33 | // EventEmmiter is the message/or/event manager 34 | EventEmmiter interface { 35 | // AddListener is an alias for .On(eventName, listener). 36 | AddListener(EventName, ...Listener) 37 | // Emit fires a particular event, 38 | // Synchronously calls each of the listeners registered for the event named 39 | // eventName, in the order they were registered, 40 | // passing the supplied arguments to each. 41 | Emit(EventName, ...interface{}) 42 | // EventNames returns an array listing the events for which the emitter has registered listeners. 43 | // The values in the array will be strings. 44 | EventNames() []EventName 45 | // GetMaxListeners returns the max listeners for this emmiter 46 | // see SetMaxListeners 47 | GetMaxListeners() int 48 | // ListenerCount returns the length of all registered listeners to a particular event 49 | ListenerCount(EventName) int 50 | // Listeners returns a copy of the array of listeners for the event named eventName. 51 | Listeners(EventName) []Listener 52 | // On registers a particular listener for an event, func receiver parameter(s) is/are optional 53 | On(EventName, ...Listener) 54 | // Once adds a one time listener function for the event named eventName. 55 | // The next time eventName is triggered, this listener is removed and then invoked. 56 | Once(EventName, ...Listener) 57 | // RemoveAllListeners removes all listeners, or those of the specified eventName. 58 | // Note that it will remove the event itself. 59 | // Returns an indicator if event and listeners were found before the remove. 60 | RemoveAllListeners(EventName) bool 61 | // RemoveListener removes given listener from the event named eventName. 62 | // Returns an indicator whether listener was removed 63 | RemoveListener(EventName, Listener) bool 64 | // Clear removes all events and all listeners, restores Events to an empty value 65 | Clear() 66 | // SetMaxListeners obviously this function allows the MaxListeners 67 | // to be decrease or increase. Set to zero for unlimited 68 | SetMaxListeners(int) 69 | // Len returns the length of all registered events 70 | Len() int 71 | } 72 | 73 | emmiter struct { 74 | maxListeners int 75 | evtListeners Events 76 | mu sync.RWMutex 77 | } 78 | ) 79 | 80 | // CopyTo copies the event listeners to an EventEmmiter 81 | func (e Events) CopyTo(emmiter EventEmmiter) { 82 | if e != nil && len(e) > 0 { 83 | // register the events to/with their listeners 84 | for evt, listeners := range e { 85 | if len(listeners) > 0 { 86 | emmiter.AddListener(evt, listeners...) 87 | } 88 | } 89 | } 90 | } 91 | 92 | // New returns a new, empty, EventEmmiter 93 | func New() EventEmmiter { 94 | return &emmiter{maxListeners: DefaultMaxListeners, evtListeners: Events{}} 95 | } 96 | 97 | var ( 98 | _ EventEmmiter = &emmiter{} 99 | defaultEmmiter = New() 100 | ) 101 | 102 | // AddListener is an alias for .On(eventName, listener). 103 | func AddListener(evt EventName, listener ...Listener) { 104 | defaultEmmiter.AddListener(evt, listener...) 105 | } 106 | 107 | func (e *emmiter) AddListener(evt EventName, listener ...Listener) { 108 | if len(listener) == 0 { 109 | return 110 | } 111 | 112 | e.mu.Lock() 113 | defer e.mu.Unlock() 114 | 115 | if e.evtListeners == nil { 116 | e.evtListeners = Events{} 117 | } 118 | 119 | listeners := e.evtListeners[evt] 120 | 121 | if e.maxListeners > 0 && len(listeners) == e.maxListeners { 122 | if EnableWarning { 123 | log.Printf(`(events) warning: possible EventEmitter memory ' 124 | leak detected. %d listeners added. ' 125 | Use emitter.SetMaxListeners(n int) to increase limit.`, len(listeners)) 126 | } 127 | return 128 | } 129 | 130 | if listeners == nil { 131 | listeners = make([]Listener, e.maxListeners) 132 | } 133 | 134 | e.evtListeners[evt] = append(listeners, listener...) 135 | } 136 | 137 | // Emit fires a particular event, 138 | // Synchronously calls each of the listeners registered for the event named 139 | // eventName, in the order they were registered, 140 | // passing the supplied arguments to each. 141 | func Emit(evt EventName, data ...interface{}) { 142 | defaultEmmiter.Emit(evt, data...) 143 | } 144 | 145 | func (e *emmiter) Emit(evt EventName, data ...interface{}) { 146 | e.mu.RLock() 147 | defer e.mu.RUnlock() 148 | 149 | if e.evtListeners == nil { 150 | return // has no listeners to emit/speak yet 151 | } 152 | if listeners := e.evtListeners[evt]; len(listeners) > 0 { 153 | for i := range listeners { 154 | l := listeners[i] 155 | if l != nil { 156 | l(data...) 157 | } 158 | } 159 | } 160 | } 161 | 162 | // EventNames returns an array listing the events for which the emitter has registered listeners. 163 | // The values in the array will be strings. 164 | func EventNames() []EventName { 165 | return defaultEmmiter.EventNames() 166 | } 167 | 168 | func (e *emmiter) EventNames() []EventName { 169 | if e.evtListeners == nil || e.Len() == 0 { 170 | return nil 171 | } 172 | 173 | names := make([]EventName, 0, e.Len()) 174 | i := 0 175 | for k := range e.evtListeners { 176 | names = append(names, k) 177 | i++ 178 | } 179 | return names 180 | } 181 | 182 | // GetMaxListeners returns the max listeners for this emmiter 183 | // see SetMaxListeners 184 | func GetMaxListeners() int { 185 | return defaultEmmiter.GetMaxListeners() 186 | } 187 | 188 | func (e *emmiter) GetMaxListeners() int { 189 | return e.maxListeners 190 | } 191 | 192 | // ListenerCount returns the length of all registered listeners to a particular event 193 | func ListenerCount(evt EventName) int { 194 | return defaultEmmiter.ListenerCount(evt) 195 | } 196 | 197 | func (e *emmiter) ListenerCount(evt EventName) (count int) { 198 | e.mu.RLock() 199 | evtListeners := e.evtListeners[evt] 200 | e.mu.RUnlock() 201 | 202 | return e.listenerCount(evtListeners) 203 | } 204 | 205 | func (e *emmiter) listenerCount(evtListeners []Listener) (count int) { 206 | for _, l := range evtListeners { 207 | if l == nil { 208 | continue 209 | } 210 | count++ 211 | } 212 | 213 | return 214 | } 215 | 216 | // Listeners returns a copy of the array of listeners for the event named eventName. 217 | func Listeners(evt EventName) []Listener { 218 | return defaultEmmiter.Listeners(evt) 219 | } 220 | 221 | func (e *emmiter) Listeners(evt EventName) []Listener { 222 | if e.evtListeners == nil { 223 | return nil 224 | } 225 | var listeners []Listener 226 | if evtListeners := e.evtListeners[evt]; evtListeners != nil { 227 | // do not pass any inactive/removed listeners(nil) 228 | for _, l := range evtListeners { 229 | if l == nil { 230 | continue 231 | } 232 | 233 | listeners = append(listeners, l) 234 | } 235 | 236 | if len(listeners) > 0 { 237 | return listeners 238 | } 239 | } 240 | 241 | return nil 242 | } 243 | 244 | // On registers a particular listener for an event, func receiver parameter(s) is/are optional 245 | func On(evt EventName, listener ...Listener) { 246 | defaultEmmiter.On(evt, listener...) 247 | } 248 | 249 | func (e *emmiter) On(evt EventName, listener ...Listener) { 250 | e.AddListener(evt, listener...) 251 | } 252 | 253 | // Once adds a one time listener function for the event named eventName. 254 | // The next time eventName is triggered, this listener is removed and then invoked. 255 | func Once(evt EventName, listener ...Listener) { 256 | defaultEmmiter.Once(evt, listener...) 257 | } 258 | 259 | type oneTimelistener struct { 260 | evt EventName 261 | emitter *emmiter 262 | listener Listener 263 | fired int32 264 | executeRef Listener 265 | } 266 | 267 | func (l *oneTimelistener) execute(vals ...interface{}) { 268 | if atomic.CompareAndSwapInt32(&l.fired, 0, 1) { 269 | l.listener(vals...) 270 | go l.emitter.RemoveListener(l.evt, l.executeRef) 271 | } 272 | } 273 | 274 | func (e *emmiter) Once(evt EventName, listener ...Listener) { 275 | if len(listener) == 0 { 276 | return 277 | } 278 | 279 | var modifiedListeners []Listener 280 | 281 | for _, listener := range listener { 282 | oneTime := &oneTimelistener{ 283 | evt: evt, 284 | emitter: e, 285 | listener: listener, 286 | } 287 | oneTime.executeRef = oneTime.execute 288 | modifiedListeners = append(modifiedListeners, oneTime.executeRef) 289 | } 290 | e.AddListener(evt, modifiedListeners...) 291 | } 292 | 293 | // RemoveAllListeners removes all listeners, or those of the specified eventName. 294 | // Note that it will remove the event itself. 295 | // Returns an indicator if event and listeners were found before the remove. 296 | func RemoveAllListeners(evt EventName) bool { 297 | return defaultEmmiter.RemoveAllListeners(evt) 298 | } 299 | 300 | func (e *emmiter) RemoveAllListeners(evt EventName) bool { 301 | e.mu.Lock() 302 | defer e.mu.Unlock() 303 | 304 | if e.evtListeners == nil { 305 | return false // has nothing to remove 306 | } 307 | 308 | if listeners, ok := e.evtListeners[evt]; ok { 309 | count := e.listenerCount(listeners) 310 | delete(e.evtListeners, evt) 311 | return count > 0 312 | } 313 | 314 | return false 315 | } 316 | 317 | // RemoveListener removes the specified listener from the listener array for the event named eventName. 318 | func (e *emmiter) RemoveListener(evt EventName, listener Listener) bool { 319 | if e.evtListeners == nil { 320 | return false 321 | } 322 | 323 | if listener == nil { 324 | return false 325 | } 326 | 327 | e.mu.Lock() 328 | defer e.mu.Unlock() 329 | 330 | listeners := e.evtListeners[evt] 331 | 332 | if listeners == nil { 333 | return false 334 | } 335 | 336 | idx := -1 337 | listenerPointer := reflect.ValueOf(listener).Pointer() 338 | 339 | for index, item := range listeners { 340 | itemPointer := reflect.ValueOf(item).Pointer() 341 | if itemPointer == listenerPointer { 342 | idx = index 343 | break 344 | } 345 | } 346 | 347 | if idx < 0 { 348 | return false 349 | } 350 | 351 | var modifiedListeners []Listener = nil 352 | 353 | if len(listeners) > 1 { 354 | modifiedListeners = append(listeners[:idx], listeners[idx+1:]...) 355 | } 356 | 357 | e.evtListeners[evt] = modifiedListeners 358 | 359 | return true 360 | } 361 | 362 | // Clear removes all events and all listeners, restores Events to an empty value 363 | func Clear() { 364 | defaultEmmiter.Clear() 365 | } 366 | 367 | func (e *emmiter) Clear() { 368 | e.evtListeners = Events{} 369 | } 370 | 371 | // SetMaxListeners obviously this function allows the MaxListeners 372 | // to be decrease or increase. Set to zero for unlimited 373 | func SetMaxListeners(n int) { 374 | defaultEmmiter.SetMaxListeners(n) 375 | } 376 | 377 | func (e *emmiter) SetMaxListeners(n int) { 378 | if n < 0 { 379 | if EnableWarning { 380 | log.Printf("(events) warning: MaxListeners must be positive number, tried to set: %d", n) 381 | return 382 | } 383 | } 384 | e.maxListeners = n 385 | } 386 | 387 | // Len returns the length of all registered events 388 | func Len() int { 389 | return defaultEmmiter.Len() 390 | } 391 | 392 | func (e *emmiter) Len() int { 393 | if e.evtListeners == nil { 394 | return 0 395 | } 396 | return len(e.evtListeners) 397 | } 398 | -------------------------------------------------------------------------------- /events_test.go: -------------------------------------------------------------------------------- 1 | package events 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | "time" 7 | ) 8 | 9 | var testEvents = Events{ 10 | "user_created": []Listener{ 11 | func(payload ...interface{}) { 12 | fmt.Printf("A new User just created!\n") 13 | }, 14 | func(payload ...interface{}) { 15 | fmt.Printf("A new User just created, *from second event listener\n") 16 | }, 17 | }, 18 | "user_joined": []Listener{func(payload ...interface{}) { 19 | user := payload[0].(string) 20 | room := payload[1].(string) 21 | fmt.Printf("%s joined to room: %s\n", user, room) 22 | }}, 23 | "user_left": []Listener{func(payload ...interface{}) { 24 | user := payload[0].(string) 25 | room := payload[1].(string) 26 | fmt.Printf("%s left from the room: %s\n", user, room) 27 | }}, 28 | } 29 | 30 | func createUser(user string) { 31 | Emit("user_created", user) 32 | } 33 | 34 | func joinUserTo(user string, room string) { 35 | Emit("user_joined", user, room) 36 | } 37 | 38 | func leaveFromRoom(user string, room string) { 39 | Emit("user_left", user, room) 40 | } 41 | 42 | func ExampleEvents() { 43 | // regiter our events to the default event emmiter 44 | for evt, listeners := range testEvents { 45 | On(evt, listeners...) 46 | } 47 | 48 | user := "user1" 49 | room := "room1" 50 | 51 | createUser(user) 52 | joinUserTo(user, room) 53 | leaveFromRoom(user, room) 54 | 55 | // Output: 56 | // A new User just created! 57 | // A new User just created, *from second event listener 58 | // user1 joined to room: room1 59 | // user1 left from the room: room1 60 | } 61 | 62 | func TestEvents(t *testing.T) { 63 | e := New() 64 | expectedPayload := "this is my payload" 65 | 66 | e.On("my_event", func(payload ...interface{}) { 67 | if len(payload) <= 0 { 68 | t.Fatal("Expected payload but got nothing") 69 | } 70 | 71 | if s, ok := payload[0].(string); !ok { 72 | t.Fatalf("Payload is not the correct type, got: %#v", payload[0]) 73 | } else if s != expectedPayload { 74 | t.Fatalf("Eexpected %s, got: %s", expectedPayload, s) 75 | } 76 | }) 77 | 78 | e.Emit("my_event", expectedPayload) 79 | if e.Len() != 1 { 80 | t.Fatalf("Length of the events is: %d, while expecting: %d", e.Len(), 1) 81 | } 82 | 83 | if e.Len() != 1 { 84 | t.Fatalf("Length of the listeners is: %d, while expecting: %d", e.ListenerCount("my_event"), 1) 85 | } 86 | 87 | e.RemoveAllListeners("my_event") 88 | if e.Len() != 0 { 89 | t.Fatalf("Length of the events is: %d, while expecting: %d", e.Len(), 0) 90 | } 91 | 92 | if e.Len() != 0 { 93 | t.Fatalf("Length of the listeners is: %d, while expecting: %d", e.ListenerCount("my_event"), 0) 94 | } 95 | } 96 | 97 | func TestEventsOnce(t *testing.T) { 98 | // on default 99 | Clear() 100 | 101 | var count = 0 102 | Once("my_event", func(payload ...interface{}) { 103 | if count > 0 { 104 | t.Fatalf("Once's listener fired more than one time! count: %d", count) 105 | } 106 | if payload[0] != "foo" { 107 | t.Fatalf("Once's listener payload is incorrect: %+v", payload) 108 | } 109 | count++ 110 | }) 111 | 112 | if l := ListenerCount("my_event"); l != 1 { 113 | t.Fatalf("Real event's listeners should be: %d but has: %d", 1, l) 114 | } 115 | 116 | if l := len(Listeners("my_event")); l != 1 { 117 | t.Fatalf("Real event's listeners (from Listeners) should be: %d but has: %d", 1, l) 118 | } 119 | 120 | for i := 0; i < 10; i++ { 121 | Emit("my_event", "foo") 122 | } 123 | 124 | time.Sleep(10 * time.Millisecond) 125 | 126 | if l := ListenerCount("my_event"); l > 0 { 127 | t.Fatalf("Real event's listeners length count should be: %d but has: %d", 0, l) 128 | } 129 | 130 | if l := len(Listeners("my_event")); l > 0 { 131 | t.Fatalf("Real event's listeners length count ( from Listeners) should be: %d but has: %d", 0, l) 132 | } 133 | 134 | } 135 | 136 | func TestRemoveListener(t *testing.T) { 137 | // on default 138 | e := New() 139 | 140 | var count = 0 141 | listener := func(payload ...interface{}) { 142 | if count > 1 { 143 | t.Fatal("Event listener should be removed") 144 | } 145 | 146 | count++ 147 | } 148 | 149 | e.AddListener("my_event", listener) 150 | e.AddListener("my_event", func(payload ...interface{}) {}) 151 | e.AddListener("another_event", func(payload ...interface{}) {}) 152 | 153 | e.Emit("my_event") 154 | 155 | if e.RemoveListener("my_event", listener) != true { 156 | t.Fatal("Should return 'true' when removes found listener") 157 | } 158 | 159 | if e.RemoveListener("foo_bar", listener) != false { 160 | t.Fatal("Should return 'false' when removes nothing") 161 | } 162 | 163 | if e.Len() != 2 { 164 | t.Fatal("Length of all listeners must be 2") 165 | } 166 | 167 | if e.ListenerCount("my_event") != 1 { 168 | t.Fatal("Length of 'my_event' event listeners must be 1") 169 | } 170 | 171 | e.Emit("my_event") 172 | } 173 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/kataras/go-events 2 | 3 | go 1.19 4 | -------------------------------------------------------------------------------- /logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kataras/go-events/91567b08c4a76786bae41b5d344d50cf20db3b4d/logo.jpg --------------------------------------------------------------------------------