使用go-redis存储Proto序列化Redis Hash并反序列化到结构体遇问题求助
解决Redis HGETALL反序列化Proto结构体的问题
问题根源
HGETALL命令返回的是Redis Hash的键值对交替切片([]interface{}),而非单个字符串。你的代码错误地尝试将其直接转换为string,导致无法获取到正确的Proto序列化字节数据;而HGET仅返回单个字段的值,因此可以正常转换处理。
解决方案
方案1:提取Hash中指定字段的值反序列化
如果你的目标是从Hash中获取style字段并解析为CMSStyleRedisEntry,只需遍历HGETALL返回的键值对切片,提取对应字段的序列化值:
import "fmt" var res interface{} res, err = redis.GoRedisInstance().Do(context.Background(), "HGETALL", key).Result() if err != nil { return nil, false, err } // 断言为键值对切片 kvPairs, ok := res.([]interface{}) if !ok { return nil, false, fmt.Errorf("HGETALL返回格式错误") } var styleBytes []byte // 遍历交替的键值对,找到目标字段 for i := 0; i < len(kvPairs); i += 2 { keyStr, ok := kvPairs[i].(string) if !ok { continue } if keyStr == "style" { valStr, ok := kvPairs[i+1].(string) if ok { styleBytes = []byte(valStr) break } } } if len(styleBytes) == 0 { return nil, false, fmt.Errorf("未找到style字段") } styleEntry, err := parseStyle(ctx, styleBytes)
方案2:解析Hash中所有字段组装结构体
如果CMSStyleRedisEntry包含Hash中的多个字段,需逐个解析每个字段的序列化值并组装结构体:
func parseStyleFromHash(kvPairs []interface{}) (*style_fetch.CMSStyleRedisEntry, error) { entry := &style_fetch.CMSStyleRedisEntry{} for i := 0; i < len(kvPairs); i += 2 { keyStr, ok := kvPairs[i].(string) if !ok { continue } valStr, ok := kvPairs[i+1].(string) if !ok { continue } valBytes := []byte(valStr) switch keyStr { case "style": var style style_fetch.Style if err := proto.Unmarshal(valBytes, &style); err != nil { return nil, err } entry.Style = &style case "id": // 示例:如果id是序列化的int32字段 var id int32 if err := proto.Unmarshal(valBytes, &id); err != nil { return nil, err } entry.Id = id // 如果id是直接存储的字符串,直接赋值:entry.Id = valStr } } return entry, nil } // 调用示例 kvPairs, ok := res.([]interface{}) if !ok { return nil, false, fmt.Errorf("HGETALL返回格式错误") } styleEntry, err := parseStyleFromHash(kvPairs)
额外建议
如果你的需求是存储整个CMSStyleRedisEntry结构体,无需使用Redis Hash,直接用SET/GET命令存储整个Proto序列化后的字节数组更简单,避免HGETALL的解析复杂度:
// 存储 data, err := proto.Marshal(styleEntry) if err != nil { // 处理错误 } err = redis.GoRedisInstance().Set(context.Background(), key, data, 0).Err() // 读取 data, err := redis.GoRedisInstance().Get(context.Background(), key).Bytes() if err != nil { // 处理错误 } var entry style_fetch.CMSStyleRedisEntry err = proto.Unmarshal(data, &entry)
内容的提问来源于stack exchange,提问作者Jyoti Kumari
相关产品推荐
相关产品推荐

