go中中介者模式的核心是解耦多组件交互,通过窄而具体的接口(如mediator)、同事持接口而非具体实现、显式注入、避免上帝对象来实现。

Go 里用中介者模式,不是为了“套设计模式”,而是当三个以上组件开始互相传参、加 if user.Type == "admin"、改一个文件要动五个包时,它就是最自然的解耦出口。
用接口定义 Mediator,别写抽象基类
Go 没有抽象类,也别试图造 type AbstractMediator interface{...}。直接定义行为契约即可,窄而具体:
-
type Mediator interface { Send(from, to, msg string) }—— 私聊/广播都靠to字符串区分,调试直观,无泛型负担 - 避免
Notify(sender interface{}, data interface{}):类型断言满天飞,测试难覆盖,data一变,所有switch v.(type)都得改 - 接口方法名要有业务语义,比如
BroadcastMessage()或RouteOrderEvent(),别叫Handle()或Process()
同事对象只持接口,不存具体实现指针
每个同事(如 User、Notifier)结构体里字段必须是 Mediator 接口,不是 *ChatRoom 或 *LoginMediator:
- 否则会引发循环导入:同事包 import 中介者包 → 中介者包又 import 同事包 → 编译失败
- 测试时无法注入 mock 实现,比如用
testMediator捕获调用断言 - 初始化必须显式传入,禁止懒加载或全局单例:
u := &User{mediator: room},不是u := &User{}再补u.SetMediator(room)(后者极易漏调,导致nil panic)
中介者内部用 map[string]any 或具体类型字段,别硬塞 interface{}
中介者结构体怎么存协作方?取决于你是否需要动态增删或跨包复用:
产品介绍微趣能 Weiqn 开源免费的微信公共账号接口系统。MVC框架框架结构清晰、易维护、模块化、扩展性好,性能稳定强大核心-梦有多大核心就有多大,轻松应对各种场景!微趣能系统 以关键字应答为中心 与内容素材库 文本 如图片 语音 视频和应用各类信息整体汇集并且与第三方应用完美结合,强大的前后台管理;人性化的界面设计。开放API接口-灵活多动的API,万名开发者召集中。Weiqn 系统开发者AP
立即学习“go语言免费学习笔记(深入)”;
- 若协作方固定且类型明确(如日志器、通知器、历史记录器),直接字段组合:
logger *Logger、notifier NotificationService—— 类型安全、零反射、性能好 - 若需运行时注册多个同类型处理器(如多个
MetricsCollector),用handlers map[string][]func(event string, data interface{}),但记得提供Register(name string, h func(...))和Unregister(name string) - 绝对避免
colleagues []interface{}+ 类型断言:失去编译检查,panic 风险高,IDE 无法跳转
警惕“中介者变上帝对象”的三个信号
一个中介者开始失控,往往不是代码写错了,而是职责边界模糊了:
- 结构体字段超过 5 个,且横跨登录、聊天、文件、权限多个域 → 拆成
LoginMediator、ChatMediator等独立小中介者 -
Send()方法里出现if event == "login" { ... } else if event == "upload" { ... }→ 这已不是协调,是路由+业务逻辑混合体,应交由事件总线或命令分发器 - 新增一个功能(如埋点上报)要改中介者、改所有同事的
Receive()、还要加新字段 → 说明中介者暴露了太多内部细节,应封装为m.RecordMetric("msg_sent", u.name),不暴露metricsCollector字段
真正难的从来不是写出 type ChatRoom struct { users map[string]*User },而是每次想在 User.Send() 里加一行 log.Printf 时,能忍住不去动它,而是打开 ChatRoom.BroadcastMessage() —— 因为那里才是通信逻辑的唯一信源。









