在 Go 中,可以使用接口和通道实现一个简单的监听器(Observer)模式。以下是一个简单的示例:
package main
import (
"fmt"
"sync"
"time"
)
// 定义事件结构体
type Event struct {
Message string
}
// 定义监听器接口
type Listener interface {
Notify(event Event)
}
// 定义事件源结构体
type EventSource struct {
listeners []Listener
mutex sync.Mutex
}
// 添加监听器
func (es *EventSource) AddListener(listener Listener) {
es.mutex.Lock()
defer es.mutex.Unlock()
es.listeners = append(es.listeners, listener)
}
// 移除监听器
func (es *EventSource) RemoveListener(listener Listener) {
es.mutex.Lock()
defer es.mutex.Unlock()
for i, l := range es.listeners {
if l == listener {
es.listeners = append(es.listeners[:i], es.listeners[i+1:]...)
break
}
}
}
// 发送事件通知给所有监听器
func (es *EventSource) NotifyAll(event Event) {
es.mutex.Lock()
defer es.mutex.Unlock()
for _, listener := range es.listeners {
go listener.Notify(event)
}
}
// 实现监听器接口的具体结构体
type ConcreteListener struct {
Name string
}
func (cl ConcreteListener) Notify(event Event) {
fmt.Printf("[%s] Received event: %s\n", cl.Name, event.Message)
}
func main() {
// 创建事件源
eventSource := &EventSource{}
// 创建监听器并添加到事件源
listener1 := ConcreteListener{Name: "Listener 1"}
listener2 := ConcreteListener{Name: "Listener 2"}
eventSource.AddListener(listener1)
eventSource.AddListener(listener2)
// 模拟事件并通知监听器
event := Event{Message: "Something happened!"}
eventSource.NotifyAll(event)
// 等待一段时间以便观察输出
time.Sleep(time.Second)
}
在这个示例中,我们定义了 Event
结构体表示事件,Listener
接口定义了监听器的行为,EventSource
结构体表示事件源。具体的监听器实现了 Listener
接口。在 main
函数中,我们创建了事件源和两个具体的监听器,然后将监听器添加到事件源,并通过事件源通知所有监听器。
请注意,这只是一个简单的示例,实际中可能需要更复杂的设计,特别是在多并发场景下需要考虑并发安全性。此外,Go 中还有其他方式实现观察者模式,比如使用 context
包、sync/atomic
包等。