Go事件溯源系统多类型事件JSON反序列化优化方案咨询
Go事件溯源JSON反序列化优化方案
核心思路是用事件类型注册表替代硬编码的switch分支,新增事件时只需注册无需修改反序列化逻辑,完美解决多事件类型下的代码冗余问题。
实现步骤
1. 定义全局注册表与注册方法
package main import ( "encoding/json" "reflect" "strings" ) // IEvent 所有事件需实现的公共接口,可根据业务扩展方法 type IEvent interface{} // 全局事件注册表:事件类型名 -> 对应事件的反射类型 var eventRegistry = make(map[string]reflect.Type) // RegisterEventType 注册事件类型,传入事件指针实例即可完成注册 func RegisterEventType(e IEvent) { t := reflect.TypeOf(e).Elem() eventRegistry[t.Name()] = t }
2. 事件结构体自行完成注册
每个事件定义完成后,在同文件的init函数中完成注册,无需修改公共反序列化代码:
// UserCreated 用户创建事件示例 type UserCreated struct { UserID int64 `json:"user_id"` Name string `json:"name"` } func init() { RegisterEventType(&UserCreated{}) } // EmailChanged 邮箱修改事件示例 type EmailChanged struct { UserID int64 `json:"user_id"` NewEmail string `json:"new_email"` } func init() { RegisterEventType(&EmailChanged{}) }
3. 重写反序列化方法,移除switch分支
type TypedJson struct { Type string `json:"type"` Data json.RawMessage `json:"data"` } // SerializeJson 序列化方法基本保持不变,兼容原有逻辑 func SerializeJson(event IEvent) []byte { data, _ := json.Marshal(event) dataType := reflect.TypeOf(event) if dataType.Kind() == reflect.Ptr { dataType = dataType.Elem() } typedThing := TypedJson{ Type: dataType.Name(), Data: data, } finalJson, _ := json.Marshal(typedThing) return finalJson } // Deserialize 无switch分支的反序列化实现 func Deserialize(jsonData []byte) (IEvent, error) { var wrapper TypedJson if err := json.Unmarshal(jsonData, &wrapper); err != nil { return nil, err } // 从注册表查找对应事件类型 eventType, exist := eventRegistry[wrapper.Type] if !exist { return nil, nil // 可根据业务需要返回未知事件类型错误 } // 反射创建事件实例并解析Data eventInstance := reflect.New(eventType).Interface() if err := json.Unmarshal(wrapper.Data, eventInstance); err != nil { return nil, err } // 若需要返回值类型而非指针,可替换为下面的返回逻辑: // return reflect.ValueOf(eventInstance).Elem().Interface(), nil return eventInstance, nil }
优化优势
- 符合开闭原则:新增事件只需要在对应事件定义文件中完成注册,无需修改公共反序列化逻辑
- 代码简洁:完全消除了冗长的switch分支,可维护性大幅提升
- 可扩展性强:可根据需要扩展注册逻辑,比如增加包名前缀避免同名事件冲突、注册事件校验逻辑等
性能优化提示
如果是极高吞吐的业务场景,可将注册表改造为存储构造函数,避免反射性能损耗:
// 构造函数类型注册表 var eventRegistry = make(map[string]func() IEvent) // 注册时传入构造函数 func RegisterEventType(typeName string, constructor func() IEvent) { eventRegistry[typeName] = constructor } // 注册示例 func init() { RegisterEventType("UserCreated", func() IEvent { return &UserCreated{} }) } // 反序列化时直接调用构造函数创建实例 constructor := eventRegistry[wrapper.Type] eventInstance := constructor()
内容的提问来源于stack exchange,提问作者GioGio
相关产品推荐
相关产品推荐

