go语言中直接套用经典中介者模式别扭,因其缺乏类继承和抽象类,强制接口实现易导致代码冗重、误用空接口;go更倾向用组合、函数值、隐式接口和channel实现解耦通信。

为什么 Go 语言里直接套用经典中介者模式会别扭
因为 Go 没有类继承、没有抽象类、也没有接口的强制实现约束,照搬 UML 类图里的 Mediator 抽象基类 + Colleague 抽象角色那一套,反而会让代码变重、接口膨胀,还容易误用空接口或反射硬凑。Go 更倾向用组合、函数值、接口隐式满足和 channel 协调来达成“解耦通信”这个本质目标。
用 interface + struct 组合实现轻量中介者
核心是定义一个清晰的通信契约接口,让同事对象只依赖它,不互相持有引用。中介者本身是个具体 struct,内部可维护状态或转发逻辑。
-
Mediator接口只需声明关键协作方法,例如Notify(sender string, event string, data interface{}) - 每个同事(如
User、ChatRoom)内嵌一个mediator Mediator字段,构造时注入 - 同事触发行为时调用
m.mediator.Notify("user-123", "msg_sent", msg),而非直接调用另一方方法 - 中介者实现里可做路由判断:比如根据
event是"join"还是"leave",决定通知哪些同事
用 channel 替代方法调用做异步中介协调
当协作涉及耗时操作(如日志写入、通知推送)或需解耦执行时机时,channel 比同步方法调用更符合 Go 的并发哲学。
本书是全面讲述PHP与MySQL的经典之作,书中不但全面介绍了两种技术的核心特性,还讲解了如何高效地结合这两种技术构建健壮的数据驱动的应用程序。本书涵盖了两种技术新版本中出现的最新特性,书中大量实际的示例和深入的分析均来自于作者在这方面多年的专业经验,可用于解决开发者在实际中所面临的各种挑战。
- 定义事件结构体:
type Event struct { Type string; From string; Payload interface{} } - 中介者持有一个
events chan Event,同事向它发送事件:mediator.events - 中介者启动 goroutine 消费:
go func() { for e := range mediator.events { /* 路由/广播/过滤 */ } }() - 避免在同事中直接写
select或阻塞读 —— 那会让职责倒置,中介者应掌控分发节奏
常见踩坑点:循环依赖与生命周期错位
中介者模式最容易在 Go 中引发隐式循环引用,尤其当同事结构体字段直接持有了中介者指针,而中介者又缓存了同事指针列表时。
立即学习“go语言免费学习笔记(深入)”;
- 不要在中介者里用
map[string]*User缓存所有同事实例 —— 改用 ID + 回调函数注册,例如Register(id string, handler func(Event)) - 同事对象销毁时,务必调用中介者的
Unregister(id),否则造成内存泄漏和僵尸 handler - 避免中介者方法里直接调用同事的导出方法(如
u.SendMessage()),改用统一事件或回调,否则破坏封装边界 - 测试时容易漏掉并发场景:多个 goroutine 同时
Notify,中介者的事件 channel 或 map 操作需加锁或用 sync.Map
真正难的不是写出结构,而是判断什么时候该用中介者——比如当三个以上组件开始用全局变量、单例或互相 import 包级函数通信时,就该把那团胶水逻辑拎出来,用一个明确的 Mediator 接口和它的实现收口。否则很快就会在 main.go 或工具包里看到一堆难以追踪的跨模块调用。









