go-redis HGETALL protobuf message

huangapple go评论65阅读模式
英文:

go-redis HGETALL protobuf message

问题

大家有没有尝试将Redis哈希存储为Proto Marshalled,并在结构中进行解组和检索?我在这方面遇到了问题。
我尝试以下步骤,但无法获得期望的结果:

  1. 定义一个接口
  2. 执行HGETALL并尝试将结果存储在上述接口中
  3. 转换为字节数组
  4. 将其解析为所需的结构体

注意:使用github.com/go-redis/redis/v8中的redis.NewClusterClient

var res interface{}
res, err = redis.GoRedisInstance().Do(context.Background(), "HGETALL", key).Result()
if err != nil {
    return nil, false, err
}
if response, ok := res.(string); ok {
    value = []byte(response)
}
styleEntry, err := parseStyle(ctx, value)
func parseStyle(ctx context.Context, b []byte) (*style_fetch.CMSStyleRedisEntry, error) {
    // 转换为产品Redis对象
    productRedis := style_fetch.CMSStyleRedisEntry{}
    err := proto.Unmarshal(b, &productRedis)
    if err != nil {
        return nil, err
    }
    return &productRedis, nil
}

在调试时,我看到redis.GoRedisInstance().Do(context.Background(), "HGETALL", key)返回的是interface{}([]interface{}),其中:

  • key是interface{}(string)
  • value(Proto Marshalled)是interface{}(string)
    附上了快照,请参考这里

但是,对于.Result(),两者都返回了无法解析的接口类型。

对于HGET命令,它是有效的:

res, err = redis.GoRedisInstance().Do(context.Background(), "HGET", key, "style").Result()
style := style_fetch.Style{}
err := proto.Unmarshal(b, &style)
if err != nil {
    return nil, err
}
productRedis := &style_fetch.CMSStyleRedisEntry{Style: &style}
return productRedis, nil
英文:

Hi has anyone tried storing redis hash as proto marshalled and unmarshall and retrieve in struct? I am facing issue in that.
Doing below but not able to get desired result

  1. defining an interface
  2. Execution HGETALL and trying to get result in above interface
  3. converting to byte array
  4. parsing it to required struct

Note: using redis.NewClusterClient from github.com/go-redis/redis/v8


    var res interface{}
    res, err = redis.GoRedisInstance().Do(context.Background(), "HGETALL", key).Result()
    if err != nil {
    return nil, false, err
    }
    if response, ok := res.(string); ok {
    value = []byte(response)
    }
    styleEntry, err := parseStyle(ctx, value)


    func parseStyle(ctx context.Context, b []byte) (*style_fetch.CMSStyleRedisEntry, error) {
    // convert to product redis object
    productRedis := style_fetch.CMSStyleRedisEntry{}
    err := proto.Unmarshal(b, &productRedis)
    if err != nil {
    return nil, err
    }
    return &productRedis, nil
    }

While debugging
redis.GoRedisInstance().Do(context.Background(), "HGETALL", key)
I see interface{}([]interface{})
key - interface{}(string)
value(proto marshalled) - interface{}(string)
Attached snapshot
But .Result gives (unreadable could not resolve interface type) for both
go-redis HGETALL protobuf message

It works for HGET though
res, err = redis.GoRedisInstance().Do(context.Background(), "HGET", key, "style").Result()

style := style_fetch.Style{}
	err := proto.Unmarshal(b, &style)
	if err != nil {
		return nil, err
	}
	productRedis := &style_fetch.CMSStyleRedisEntry{Style: &style}
	return productRedis, nil```

</details>


# 答案1
**得分**: 1

**已解决**

在这里,我们需要在单个字段级别上进行协议解组,而不是在整个结构上进行解组,因为我们在这里使用的是hset/hmset单个字段。

```go
unboxed, ok := res.(map[string]string)
if !ok {
	fmt.Println("输出应该是一个指向map的指针")
}
//如果错误为nil,但值也为空/nil。在Redis中找不到数据,重新索引
if unboxed == nil || len(unboxed) <= 0 {
	//异步重新索引调用
	isCacheMiss = true
	statsd.Instance().Incr("redis.keyNotPresentError", 1)
	return nil, isCacheMiss, nil
}

redisEntry := &style_fetch.CMSStyleRedisEntry{}
for key, value := range unboxed {
	if key == "style" {
		style := &style_fetch.Style{}
		proto.Unmarshal([]byte(value), style)
		redisEntry.Style = style
	} 
           //...其他键
}

英文:

Resolved

proto unmarshall required at invidual field level and not on whole struct as here we do hset/hmset individual fields


unboxed, ok := res.(map[string]string)
if !ok {
	fmt.Println(&quot;Output should be a pointer of a map&quot;)
}
//If error is nil but value is also empty/nil. Data not found in redis, reindex
if unboxed == nil || len(unboxed) &lt;= 0 {
	//async reindexing call
	isCacheMiss = true
	statsd.Instance().Incr(&quot;redis.keyNotPresentError&quot;, 1)
	return nil, isCacheMiss, nil
}

redisEntry := &amp;style_fetch.CMSStyleRedisEntry{}
for key, value := range unboxed {
	if key == &quot;style&quot; {
		style := &amp;style_fetch.Style{}
		proto.Unmarshal([]byte(value), style)
		redisEntry.Style = style
	} 
           //...other keys
}

huangapple
  • 本文由 发表于 2022年11月10日 19:16:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/74388101.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定