Go中实现状态模式需用接口定义行为契约、结构体封装具体状态、上下文持有并委托状态行为,通过组合+接口+方法值解耦状态判断与行为逻辑,避免switch或嵌套if。

在 Go 中实现状态模式,核心是用接口定义行为契约,用结构体封装具体状态,再通过上下文对象持有当前状态并委托行为执行。Go 没有类继承,但可通过组合 + 接口 + 方法值灵活模拟状态模式语义,重点在于解耦状态判断与行为逻辑,避免大量 switch 或嵌套 if。
定义状态接口与具体状态类型
先声明一个统一的行为接口,每个状态都实现它:
// State 定义对象可响应的操作
type State interface {
Handle(ctx *Context)
GetName() string
}
// Concrete states
type IdleState struct{}
func (s *IdleState) Handle(ctx *Context) {
fmt.Println("Idle: waiting for input")
ctx.SetState(&RunningState{})
}
func (s *IdleState) GetName() string { return "idle" }
type RunningState struct{}
func (s *RunningState) Handle(ctx *Context) {
fmt.Println("Running: processing task")
ctx.SetState(&PausedState{})
}
func (s *RunningState) GetName() string { return "running" }
构建上下文(Context)管理当前状态
Context 不直接处理业务逻辑,只负责持有、切换和委托状态行为:
type Context struct {
state State
}
func NewContext() *Context {
return &Context{state: &IdleState{}}
}
func (c *Context) SetState(s State) {
c.state = s
}
func (c *Context) Handle() {
c.state.Handle(c)
}
func (c *Context) CurrentState() string {
return c.state.GetName()
}
支持状态转换的健壮性设计
实际项目中需防止非法状态跳转,可引入状态迁移规则:
立即学习“go语言免费学习笔记(深入)”;
- 在每个状态的
Handle方法里显式控制下一状态,或 - 在
SetState中校验迁移合法性(例如用 map[State][]State 定义允许的后继状态) - 添加
CanTransitionTo(to State) bool方法供前置检查 - 将状态变更封装为事件(如
ctx.Emit(EventStart{})),由状态机统一调度
替代方案:使用函数值简化轻量级状态流转
若状态行为简单、无内部字段,可用函数代替结构体:
type StateFunc func(*Context)
func (f StateFunc) Handle(ctx *Context) { f(ctx) }
func (f StateFunc) GetName() string { return "anonymous" }
// 使用时直接赋值
ctx.SetState(StateFunc(func(c *Context) {
fmt.Println("Custom one-off behavior")
c.SetState(&IdleState{})
}))










