观察者模式是“一对多”依赖关系,被观察者状态改变时自动通知所有观察者;Go通过接口、切片和函数类型简洁实现,需定义Observer接口和Subject结构体,支持并发安全注册与通知。

观察者模式的核心思路
观察者模式本质是“一对多”的依赖关系:当一个对象(被观察者)状态改变,所有依赖它的对象(观察者)自动收到通知并响应。Golang 没有内置接口或语法糖支持,但靠接口、切片和函数类型就能简洁实现,无需第三方库。
定义统一的事件通知接口
先定义一个通用的 Observer 接口,让所有观察者都实现 Update(event interface{}) 方法:
// Observer 定义观察者行为
type Observer interface {
Update(event interface{})
}
这样设计灵活:事件可以是字符串、结构体、自定义事件类型,甚至 map[string]interface{},由业务决定。
构建可观察的对象(Subject)
被观察者需维护观察者列表,并提供注册、注销、通知能力。用结构体封装状态和行为:
立即学习“go语言免费学习笔记(深入)”;
// Subject 管理观察者并触发通知
type Subject struct {
observers []Observer
mu sync.RWMutex
}
func (s *Subject) Register(o Observer) {
s.mu.Lock()
s.observers = append(s.observers, o)
s.mu.Unlock()
}
func (s *Subject) Notify(event interface{}) {
s.mu.RLock()
defer s.mu.RUnlock()
for _, o := range s.observers {
o.Update(event)
}
}
注意加锁保护并发安全——尤其在 Web 服务或定时任务中,多个 goroutine 可能同时注册或通知。
具体使用:状态变化触发事件
以用户登录状态为例,封装一个 UserSession 结构体嵌入 Subject,并在关键方法中调用 Notify:
type UserSession struct {
*Subject
ID string
IsLoggedIn bool
}
func (u *UserSession) Login() {
u.IsLoggedIn = true
u.Notify(map[string]string{
"event": "login",
"user_id": u.ID,
})
}
再写两个观察者:日志记录器和在线统计器:
type Logger struct{}
func (l Logger) Update(e interface{}) {
log.Printf("LOG: %+v", e)
}
type OnlineCounter struct{ count int }
func (c *OnlineCounter) Update(e interface{}) {
if ev, ok := e.(map[string]string); ok && ev["event"] == "login" {
c.count++
log.Printf("Online now: %d", c.count)
}
}
组合使用:
sess := &UserSession{
Subject: &Subject{},
ID: "u123",
}
sess.Register(Logger{})
counter := &OnlineCounter{}
sess.Register(counter)
sess.Login() // 触发两个观察者的 Update
这样就实现了松耦合的动态响应:新增观察者只需实现接口并注册,不修改原有逻辑。










