Go (Golang) 中的事件总线与观察者模式:实现与示例

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Go (Golang) 中的事件总线与观察者模式



在现代 Go (Golang) 开发中,经常需要组织应用程序组件之间的松散耦合交互。两种经典方法是 观察者模式 及其更高级的实现——事件总线。这些机制允许程序的一部分对其他部分的行为做出响应,而无需创建硬性依赖。



在本文中,我们将探讨如何在不依赖外部库的情况下,用纯 Go 实现事件总线,研究观察者模式,并展示同步和异步事件处理的代码示例。



什么是观察者模式?



观察者模式是一种行为设计模式,它创建了一种订阅机制,允许一个对象观察并响应另一个对象中发生的事件。



主要元素:

  • 主题 — 生成事件的对象。
  • 观察者 — 订阅事件的对象。
  • 事件 — 从主题传递给观察者的数据。


什么是事件总线?



事件总线是一个集中式总线,用于管理发布者和订阅者之间的事件传递。与经典的观察者模式不同(其中主题直接存储观察者列表),事件总线充当中介。这使得系统更加灵活和可扩展。



在 Go 中实现事件总线



Go 没有内置的事件总线实现,但可以使用 goroutine、通道和接口轻松编写。让我们看一个简单但功能完整的实现。



1. 定义基本类型



// Event 表示事件结构type Event struct {    Name string    Data interface{}}

// EventHandler — 事件处理函数type EventHandler func(Event)


2. 创建事件总线



type EventBus struct {    handlers map[string][]EventHandler    mu       sync.RWMutex}

// NewEventBus 创建一个新的事件总线func NewEventBus() *EventBus { return &EventBus{ handlers: make(map[string][]EventHandler), }}

// Subscribe 将处理程序订阅到事件func (eb *EventBus) Subscribe(name string, handler EventHandler) { eb.mu.Lock() defer eb.mu.Unlock() eb.handlers[name] = append(eb.handlers[name], handler)}

// Publish 同步发布事件func (eb *EventBus) Publish(name string, data interface{}) { eb.mu.RLock() defer eb.mu.RUnlock() if handlers, ok := eb.handlers[name]; ok { event := Event{Name: name, Data: data} for _, handler := range handlers { handler(event) } }}


3. 异步发布



对于异步处理,可以在单独的 goroutine 中运行每个处理程序:



// PublishAsync 异步发布事件func (eb *EventBus) PublishAsync(name string, data interface{}) {    eb.mu.RLock()    defer eb.mu.RUnlock()    if handlers, ok := eb.handlers[name]; ok {        event := Event{Name: name, Data: data}        for _, handler := range handlers {            go handler(event)        }    }}


使用示例



让我们看看如何在真实应用程序中使用事件总线。假设我们有一个记录用户操作并发送通知的系统。



func main() {    bus := NewEventBus()

// 订阅 "user.login" 事件 bus.Subscribe("user.login", func(e Event) { userData := e.Data.(map[string]string) fmt.Printf("日志:用户 %s 已登录系统", userData["username"]) })

// 订阅同一事件以用于

推荐