The Problem
Several workflows may share the same broad algorithm but differ in a few steps. Batch jobs, import pipelines, and sync tasks often repeat the same fetch-transform-persist structure. Duplicating the whole algorithm just to vary one stage makes the shared flow harder to maintain.
The Solution
Template Method fixes the high-level sequence while allowing specific steps to vary. In Go, this is often expressed without inheritance by using a runner function plus a small interface of hooks. The overall algorithm stays in one place, and concrete jobs provide only the variable steps.
Structure
- Template runner:
RunSyncdefines the fixed algorithm sequence. - Hook interface:
SyncHooksdeclares the steps that can vary. - Concrete jobs: Inventory and catalog sync jobs provide different fetch and transform logic.
- Client: Passes a concrete job into the runner.
Implementation
This example runs a sync pipeline with a shared algorithm: fetch records, transform them, and persist the output. Different jobs customize the step behavior without rewriting the pipeline skeleton.
package main
import "fmt"
type SyncHooks interface {
Name() string
Fetch() []string
Transform(records []string) []string
Persist(records []string) error
}
func RunSync(job SyncHooks) error {
fmt.Println("running", job.Name())
records := job.Fetch()
transformed := job.Transform(records)
return job.Persist(transformed)
} Best Practices
- Keep the fixed algorithm in one place so shared workflow changes happen once.
- Use a small hook interface that reflects only the steps that vary.
- In Go, prefer composition and function-driven hooks over inheritance-heavy designs.
- Reserve Template Method for workflows with a real stable skeleton, not just loosely similar functions.
- If the algorithm itself should vary, Strategy is usually a better fit.
When to Use
- Several workflows share the same ordered pipeline but differ in a few steps.
- You want the common sequence enforced consistently.
- Concrete jobs should customize behavior without duplicating the full algorithm.
When NOT to Use
- The steps do not actually follow one stable skeleton.
- Each workflow varies so much that a shared template becomes brittle.
- A plain helper function or Strategy would express the reuse more simply.