Go通过接口+结构体组合实现轻量状态模式:定义State接口封装行为,Machine持State接口并加锁转发请求,状态切换需避免循环引用和阻塞操作,注重并发安全与资源清理。
Go 语言没有类和继承,状态模式不能照搬传统 OOP 的写法;但通过接口 + 结构体组合 + 方法集,完全可以实现等效、更轻量的状态切换逻辑。
用 interface 定义状态行为契约
状态模式的核心是把“不同状态下对同一请求的响应”抽成统一接口。在 Go 中,这必须是一个接口,比如:
type State interface {
Handle(ctx context.Context, req *Request) error
Name() string
}
所有具体状态(如 IdleState、RunningState)都实现该接口。注意两点:
- 避免在接口中暴露过多方法——只放真正随状态变化的行为,像
Enter()或Exit()属于生命周期钩子,应由上下文结构体统一调用,不放进State接口 - 接口方法参数尽量精简,优先传值或不可变结构(如
*Request),避免传入整个上下文对象导致状态实现强耦合
用嵌入结构体实现状态切换与委托
上下文(Context)不直接持有状态值,而是持有一个 State 接口变量,并把请求转发给当前状态:
type Machine struct {
mu sync.RWMutex
state State
}
func (m *Machine) Handle(ctx context.Context, req *Request) error {
m.mu.RLock()
defer m.mu.RUnlock()
return m.state.Handle(ctx, req)
}
状态切换发生在具体操作中,例如:
func (m *Machine) Start() {
m.mu.Lock()
defer m.mu.Unlock()
m.state = &RunningState{machine: m} // 注意:这里传回指针,避免循环引用或拷贝丢失
}
关键点: