Go中命令模式用函数类型和结构体组合实现松耦合,将请求变为可存储、传递、延迟执行的一等公民:定义Command函数类型或含execute/undo字段的结构体,用闭包或结构体封装具体行为,Invoker统一调度,接收者通过闭包捕获或字段引用解耦。

命令模式在 Go 中不依赖接口继承,而是通过函数类型和结构体组合实现松耦合——核心是把“请求”变成可存储、可传递、可延迟执行的一等公民。
定义命令接口:用函数类型替代传统 interface
Go 偏好简洁,直接用函数类型 func() 表达无参无返回的命令,比定义空 interface 更轻量:
若需参数或返回值,可封装为闭包或使用带字段的结构体。例如支持撤销的命令可定义为:
type Command struct {execute func()
undo func()
}
实现具体命令:闭包或结构体都行
对某个操作(如打开文件、发送邮件)封装成命令实例,关键是把行为和上下文绑定:
立即学习“go语言免费学习笔记(深入)”;
- 用闭包快速创建一次性命令:
openCmd := func() { fmt.Println("Opening file...") } - 用结构体承载状态,适合需撤销或重试的场景:
type SaveCommand struct {
content string
file *os.File
}
func (c SaveCommand) Execute() { c.file.Write([]byte(c.content)) }
func (c SaveCommand) Undo() { c.file.Truncate(0) }
构建调用者(Invoker):统一调度,不关心具体逻辑
调用者持有命令并触发执行,也可管理历史、支持撤销/重做:
type Invoker struct {history []Command
}
func (i *Invoker) Execute(cmd Command) {
i.history = append(i.history, cmd)
cmd()
}
func (i *Invoker) Undo() {
if len(i.history) > 0 {
last := i.history[len(i.history)-1]
i.history = i.history[:len(i.history)-1]
// 实际中 undo 需单独设计,此处仅示意
}
}
连接接收者与命令:解耦关键一步
接收者(Receiver)是真正干活的对象(如 FileSaver、Notifier)。命令内部持有接收者引用或通过闭包捕获,确保执行时能调用其方法:
- 闭包方式:
notifier := &EmailNotifier{to: "admin@example.com"}
sendCmd := func() { notifier.Send("Alert: system down") } - 结构体字段方式:
cmd := SendEmailCommand{Notifier: notifier, Subject: "Urgent"}
这样调用者只认 Command 类型,完全不知道背后是发邮件还是写日志。
基本上就这些——Go 的命令模式不靠抽象层级堆砌,而靠函数即值、闭包捕获、结构体组合来自然表达意图。重点不是“像不像经典 UML”,而是让请求可序列化、可审计、可回滚、可排队。










