golang事件发射与处理插件库emitter的使用
Golang事件发射与处理插件库emitter的使用
emitter包实现了一个基于channel的发布订阅模式。设计目标是使用Golang并发模型而不是简单的回调,并设计一个非常简单的API以便于使用。
为什么选择emitter?
Go拥有强大的并发模型,但在2015年时还没有人将其很好地用于pubsub模式。emitter实现了自己的解决方案,因为它能满足特定的需求。
功能特性
- 同步/异步事件发射
- 谓词/中间件
- 双向通配符
- 需要时可取消发射
- 合并来自不同通道的事件
- 按需浅类型转换
- 支持传统回调方式
简单示例
e := &emitter.Emitter{}
go func(){
<-e.Emit("change", 42) // 等待事件成功发送
<-e.Emit("change", 37)
e.Off("*") // 取消订阅所有监听器
}()
for event := range e.On("change") {
// 处理event.Args
println(event.Int(0)) // 将第一个参数转换为int
}
// 监听器通道已关闭
构造函数
emitter.New
第一个参数是uint
类型,表示监听器的缓冲区大小。也可以在运行时通过e.Cap = 10
修改缓冲区容量。
默认情况下,emitter为每个监听器使用一个goroutine发送事件。可以通过传递emitter.Sync
标志来改变这种行为:e.Use("*", emitter.Sync)
。建议在开始时为emitter指定中间件。
通配符
包允许使用通配符进行发布和订阅。这个特性基于path.Match
函数。
示例:
go e.Emit("something:special", 42)
event := <-e.Once("*") // 搜索任何事件
println(event.Int(0)) // 会打印42
// 或者用通配符路径发射事件
go e.Emit("*", 37) // 为所有人发射
event := <-e.Once("something:special")
println(event.Int(0)) // 会打印37
中间件
中间件是一个以Event
指针为第一个参数的函数。中间件能够:
- 修改事件
- 需要时跳过事件发射
- 修改事件的参数
- 指定事件发射的模式
有两种方式添加中间件:
- 通过.On(“event”, middlewares…)
- 通过.Use(“event”, middlewares…)
示例:
// 对所有事件使用同步模式
e.Use("*", emitter.Sync)
go e.Emit("something:special", 42)
// 定义谓词
event := <-e.Once("*", func(ev *emitter.Event){
if ev.Int(0) == 42 {
// 跳过发送
ev.Flags = ev.Flags | emitter.FlagVoid
}
})
panic("永远不会发生")
标志
标志用于描述事件应该如何发射。每个事件(emitter.Event
)都有一个.Flags
字段,包含作为二进制掩码的标志。
有几种预定义的中间件来设置需要的标志:
emitter.Once
emitter.Close
emitter.Void
emitter.Skip
emitter.Sync
emitter.Reset
可以链式使用这些标志:
e.Use("*", emitter.Void) // 跳过任何事件的发送
go e.Emit("surprise", 65536)
event := <-e.On("*", emitter.Reset, emitter.Sync, emitter.Once) // 为此监听器设置自定义标志
pintln(event.Int(0)) // 打印65536
取消
可以通过关闭done通道来取消任何发射的事件:
done := e.Emit("broadcast", "the", "event", "with", "timeout")
select {
case <-done:
// 发送完成
case <-time.After(timeout):
// 超时,取消发射
close(done)
}
仅回调使用
也可以以更传统的方式使用emitter:
e := &emitter.Emitter{}
e.Use("*", emitter.Void)
go e.Emit("change", "field", "value")
e.On("change", func(event *Event){
// 在这里处理变化
field := event.String(0)
value := event.String(1)
// ...等等
})
组
组将不同的监听器合并到一个通道中:
e1 := &emitter.Emitter{}
e2 := &emitter.Emitter{}
e3 := &emitter.Emitter{}
g := &emitter.Group{Cap: 1}
g.Add(e1.On("first"), e2.On("second"), e3.On("third"))
for event := g.On() {
// 处理事件
// 事件有OriginalTopic和Topic字段
}
事件
Event是一个包含事件信息的结构体。还有一些辅助方法可以将各种参数转换为bool
、string
、float64
、int
等类型:
go e.Emit("*", "some string", 42, 37.0, true)
event := <-e.Once("*")
first := event.String(0)
second := event.Int(1)
third := event.Float(2)
fourth := event.Bool(3)
// 如果不存在则使用默认值
dontExists := event.Int(10, 64)
// 或者类型不匹配时使用默认值
def := event.Int(0, 128)
许可证
MIT
更多关于golang事件发射与处理插件库emitter的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html