diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..7aa87a5 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // 使用 IntelliSense 了解相关属性。 + // 悬停以查看现有属性的描述。 + // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Package", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${fileDirname}" + } + + ] +} \ No newline at end of file diff --git a/README.md b/README.md index c875c45..bc484ff 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,7 @@ # goemitter +go 实现类似于Nodejs中的EventEmitter + + +在协程中执行回调 + diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..7e8ca70 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module git.pyer.club/kingecg/goemitter + +go 1.19 diff --git a/goemitter_test/main.go b/goemitter_test/main.go new file mode 100644 index 0000000..1427630 --- /dev/null +++ b/goemitter_test/main.go @@ -0,0 +1,34 @@ +package main + +import ( + "fmt" + + emitter "git.pyer.club/kingecg/goemitter" +) + +type St struct { + Name string +} + +func (s *St) Print(data ...interface{}) { + fmt.Println(s.Name) + fmt.Println(data...) +} + +func main() { + + s := &St{Name: "testeer"} + em := emitter.NewEmitter() + em.On("test", func(data ...interface{}) { + fmt.Println(data...) + }) + + em.On("test", s.Print) + em.Once("test", func(data ...interface{}) { + s := fmt.Sprint(data...) + fmt.Println(interface{}("Once"), s) + }) + em.EmitSync("test", "hello", "world") + em.Emit("test", "hello", "world2") + select {} +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..ea2a26d --- /dev/null +++ b/main.go @@ -0,0 +1,77 @@ +// Package goemitter +package goemitter + +import ( + "sync" +) + +type EventEmitter struct { + callbacks map[string][]func(args ...interface{}) + onceCallbacks map[string][]func(args ...interface{}) + lock sync.Mutex +} + +func (e *EventEmitter) On(event string, callback func(args ...interface{})) { + e.lock.Lock() + defer e.lock.Unlock() + + if _, ok := e.callbacks[event]; !ok { + e.callbacks[event] = []func(args ...interface{}){callback} + } else { + e.callbacks[event] = append(e.callbacks[event], callback) + } +} + +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] = 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][]func(args ...interface{})) + ret.onceCallbacks = make(map[string][]func(args ...interface{})) + return ret +}