Go中Observer模式需手动定义Observer和Subject接口,用sync.RWMutex保护观察者列表,Notify时应复制切片再遍历,避免并发问题;事件粒度要适中,状态同步需Observer显式处理,高并发场景可改用channel优化。
Observer 模式在 Go 中没有内置接口,得自己定义 Observer 和 Subject
Go 不像 Java 或 C# 那样有语言级的观察者抽象,所以不能直接 import 一个 Observer 接口。你必须手动定义两个核心契约:Observer 接口(含 Update 方法)和 Subject 接口(含 Attach、Detach、Notify)。否则容易写成“伪观察者”——比如用闭包临时传回调,但无法动态增删监听器,也不利于测试。
典型错误是把状态变更逻辑全塞进 Notify,结果每次通知都触发完整重算,性能崩了。正确做法是让 Update 只接收必要参数(如变更字段名 + 新值),由 Observer 自行决定是否响应、如何更新局部状态。
示例最小契约:
type Observer interface {
Update(event string, data interface{})
}
type Subject interface {
Attach(obs Observer)
Detach(obs Observer)
Notify(event string, data interface{})
}
用 sync.RWMutex 保护观察者列表,避免并发 panic
多个 goroutine 同时调用 Attach/Detach 或 Notify 时,若底层用 []Observer 存储监听器,会触发 “concurrent map iteration and map write” 类似错误(即使没用 map,切片底层数组扩容也可能被并发读写破坏)。
必须加锁,且推荐 sync.RWMutex:读多写少场景下,Notify 可并发执行(只读切片),而 Attach/Detach 用写锁。