Go事件管理器:简单实现

TimLiuDream · · 875 次点击 · 开始浏览    置顶
这是一个创建于 的主题,其中的信息可能已经有所发展或是发生改变。

> 关注公众号【爱发白日梦的后端】分享技术干货、读书笔记、开源项目、实战经验、高效开发工具等,您的关注将是我的更新动力! 在编程中,事件管理器是一种常见的工具,用于通过通知来触发操作。在Go语言中,我们可以通过创建事件管理器和监听器来实现事件的处理。本文将介绍一个简单的Go事件管理器的实现,并通过异步改进提高其性能。 ## 监听器 首先,我们需要创建一个监听器。在这个实现中,监听器只是一个接收事件参数的函数。 ```go type Listener[T any] func(T) ``` ## 事件管理器 事件管理器是一个用于管理事件和监听器的结构。它具有两个方法:`Add`和`Run`。`Add`方法用于将新的监听器附加到事件上,而`Run`方法用于执行事件管理器。 ```go type Manager[T any] interface { Add(n string, l Listener[T]) Run() } ``` ## 抽象事件管理器 为了方便使用,我们可以创建一个抽象事件管理器,它实现了事件管理器接口的一部分通用逻辑。虽然Go语言并不是面向对象的,但我们可以通过模拟来实现类似的效果。 ```go type BaseManager[T any] struct { lst map[string][]Listener[T] } func (m *BaseManager[T]) Invoke(n string, args T) { for _, ls := range m.lst[n] { ls(args) } } func (m *BaseManager[T]) Add(n string, l Listener[T]) { m.lst[n] = append(m.lst[n], l) } ``` `BaseManager`提供了`Add`方法用于添加监听器和`Invoke`方法用于触发指定事件的监听器。 ## 具体事件管理器 下面是一个具体的事件管理器的示例实现:命令事件管理器。该管理器接收用户从控制台输入的命令,并根据命令类型触发相应的事件。 ```go type Command struct { Kind string Args []string } type CommandEventManager struct { BaseManager[*Command] } func (m *CommandEventManager) Run() { var ( inp string args Command ) fmt.Scanln(&inp) cmd := strings.Split(inp, ":") if l := len(cmd); l == 0 { m.Invoke("no-command", nil) } else if l > 1 { args.Args = strings.Split(cmd[1], " ") } args.Kind = cmd[0] m.Invoke("any-command", &args) m.Invoke(args.Kind, &args) } func NewCommandEventManager() Manager[*Command] { return &CommandEventManager{ BaseManager: BaseManager[*Command]{lst: make(map[string][]Listener[*Command])}, } } ``` `Run`方法获取用户从控制台输入的命令,并解析命令参数。如果没有命令或者命令参数,则触发"no-command"事件;否则,触发"any-command"事件和具体命令的事件。 ## 添加监听器 让我们向命令事件管理器添加一些监听器。 ```go func main() { cem := NewCommandEventManager() cem.Add("no-command", func(_ *Command) { fmt.Println("no command was recieved") }) cem.Add("any-command", func(c *Command) { fmt.Printf("the %s command was executed", c.Kind) }) cem.Add("sum", func(c *Command) { a, _ := strconv.Atoi(c.Args[0]) b, _ := strconv.Atoi(c.Args[1]) fmt.Printf("the sum result is: %d", a+b) }) cem.Run() } ``` 在上面的示例中,程序只执行一次,但你可以将其放在一个无限循环中以持续监听命令。 ## 异步改进 可以将事件管理器的执行改为异步方式,以提高性能。每次执行事件时,可以将其作为一个`goroutine`进行处理。甚至可以将每个监听器的执行也放在一个`goroutine`中,以提高并发性能。 通过上述改进,我们可以更好地利用Go语言的并发特性,提高事件处理效率。

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

875 次点击  ∙  1 赞  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传