基于责任链模式,按路径实现JSON到不同结构体的解码需求
解决方案:基于责任链模式实现多路径请求结构体适配
看起来你已经搭好了责任链的架子,现在需要解决不同路径对应不同请求结构体的问题,还要让createRequest组合baseRequest对吧?我给你梳理一套清晰的实现方案,直接贴代码加解释,你可以照着改:
1. 定义请求结构体(实现组合)
首先先把基础和具体请求结构体定义好,用Go的结构体嵌入实现createRequest对baseRequest的组合,这样既复用了基础字段,又能扩展特有属性:
// baseRequest 所有请求的通用基础结构体 type baseRequest struct { TraceID string `json:"trace_id"` Timestamp int64 `json:"timestamp"` } // createRequest 继承(组合)baseRequest,新增创建请求的专属字段 type createRequest struct { baseRequest // 嵌入baseRequest,自动拥有其所有字段 ResourceID string `json:"resource_id"` Quantity int `json:"quantity"` } // cancelRequest 取消请求的结构体,同样可以嵌入baseRequest复用字段 type cancelRequest struct { baseRequest OrderID string `json:"order_id"` }
2. 定义请求接口(实现多态)
为了让message.Request能兼容多种请求类型,我们定义一个空接口来标识所有请求结构体(也可以加通用方法,比如校验):
// Request 所有请求结构体的统一接口 type Request interface { // 空方法仅用于标识该类型属于请求范畴 IsRequest() } // 给每个请求结构体实现接口方法 func (*baseRequest) IsRequest() {} func (*createRequest) IsRequest() {} func (*cancelRequest) IsRequest() {}
3. 修改Message结构体
把原来的message.Request类型改成我们定义的Request接口,这样它就能容纳createRequest、cancelRequest等任意实现了接口的结构体:
// Message 责任链中传递的消息载体 type Message struct { Path string `json:"-"` // 存储请求路径,不参与JSON解码 Request Request // 现在是接口类型,支持多态 // 其他原有字段... }
4. 实现请求工厂Handler
在责任链中新增一个请求工厂Handler,它的职责就是根据请求路径创建对应类型的空结构体指针,传给后续的jsonReader()解码:
// RequestFactoryHandler 责任链中负责创建对应请求结构体的处理器 type RequestFactoryHandler struct { next Handler // 责任链下一个处理器 } func NewRequestFactoryHandler(next Handler) *RequestFactoryHandler { return &RequestFactoryHandler{next: next} } func (h *RequestFactoryHandler) Handle(msg *Message) error { // 根据路径匹配,创建对应空请求指针 switch msg.Path { case "/create": msg.Request = &createRequest{} case "/cancel": msg.Request = &cancelRequest{} default: return fmt.Errorf("unsupported request path: %s", msg.Path) } // 传递给下一个处理器(比如你的jsonReader所在的handler) if h.next != nil { return h.next.Handle(msg) } return nil }
5. 适配jsonReader()
现在你的jsonReader()可以直接用msg.Request进行解码了,因为它已经是对应类型的指针,Unmarshal会自动把JSON数据解析到正确的结构体里:
// jsonReader 从请求体解码JSON到对应的请求结构体 func jsonReader(msg *Message, requestBody []byte) error { return json.Unmarshal(requestBody, msg.Request) }
关键点说明
- 用结构体嵌入实现组合,比继承更灵活,符合Go的设计哲学;
- 用接口类型实现多态,让Message能兼容多种请求类型,不需要修改原有责任链的核心逻辑;
- 请求工厂Handler作为责任链的第一个节点,提前创建好对应结构体,后续处理器只需要专注于解码和业务逻辑,职责单一。
内容的提问来源于stack exchange,提问作者zerozero7
相关产品推荐
相关产品推荐

