Go中模板方法模式用接口定义算法步骤、结构体封装固定流程,通过组合+函数字段注入可变行为;支持泛型复用,但应避免过度设计,优先选择简单函数链或选项函数。
在 Go 语言中实现模板方法模式,核心是用接口定义算法骨架,用结构体实现具体步骤,再通过组合或函数字段“注入”可变行为——因为 Go 没有继承,所以不靠子类重写,而靠组合+接口+函数值来达成相同意图。
模板方法的本质是把不变的执行顺序(如:初始化 → 处理 → 清理)固定下来,把变化的部分(如:如何初始化、如何处理)交给实现者。Go 中可用接口描述“变化的部分”,再由某个结构体持有该接口并定义主流程:
Setup()、Execute()、Cleanup() 等方法Processor 实例,并在其 Run() 方法中按序调用这些方法Run() 流程如果步骤逻辑简单、不需状态共享,直接用函数类型字段更简洁。例如:
type Step func() error
setup, execute, cleanup Step 字段Run() 方法内依次调用:if err := w.setup(); err != nil { ... },依此类推workflow.setup = func() error { return os.MkdirAll("tmp", 0755)
}
若模板流程需适配不同输入/输出类型,可用泛型增强通用性。例如:
type Workflow[T any, R any] struct { processor Processor[T, R] }
Processor[T, R] 的 Execute(input T) (R, error) 可让同一骨架处理字符串、JSON、数据库记录等Workflow[string, int]{...} 和 Workflow[[]byte, bool]{...} 共享同一个 Run() 实现Go 崇尚“少即是多”。模板方法不是必须的,很多场景用简单函数链或选项函数(functional options)更清晰:
doSetup(); doWork(); doTeardown() 更易读nil),或用指针字段 + if w.cleanup != nil 判断