1

我有某种复杂的 protobuf 对象。这是发送到我的 GRPC 端点的请求。如果我以前没有,我只想处理它。所以我想将对象散列到某个字符串并将其存储在我的 Redis 数据库中。我使用了 ObjectHash-Proto,但使用新版本的 protobuf-compiler 我得到了这个错误:

got an unexpected struct of type 'impl.MessageState' for field {Name:state PkgPath:... Type:impl.MessageState Tag: Offset:0 Index:[0] Anonymous:false}

似乎它不支持结构和新版本的 protobuf-compiler 生成包含结构的代码。

我无法为每个请求生成某种 ID。ID实际上是整个对象的散列。

4

2 回答 2

2

如果您有proto.Message[1],那么您将免费获得 Marshal 函数 [2]。因此,在您编组消息之后,您可以将字节传递给base64md5或任何您想要的:

package main

import (
   "encoding/base64"
   "google.golang.org/protobuf/proto"
   "google.golang.org/protobuf/types/known/structpb"
)

func hash(m proto.Message) (string, error) {
   b, err := proto.Marshal(m)
   if err != nil {
      return "", err
   }
   return base64.StdEncoding.EncodeToString(b), nil
}

func main() {
   m, err := structpb.NewStruct(map[string]interface{}{
      "month": 12, "day": 31,
   })
   if err != nil {
      panic(err)
   }
   s, err := hash(m)
   if err != nil {
      panic(err)
   }
   println(s) // ChIKBW1vbnRoEgkRAAAAAAAAKEAKEAoDZGF5EgkRAAAAAAAAP0A=
}
  1. https://godocs.io/google.golang.org/protobuf/proto#Message
  2. https://godocs.io/google.golang.org/protobuf/proto#Marshal
于 2021-08-29T02:34:58.740 回答
1

原型序列化并不稳定,因此您不能依赖编组和散列输出来为同一消息生成相同的散列。

来自https://developers.google.com/protocol-buffers/docs/reference/go/faq#hash

如何使用协议缓冲区消息作为哈希键?

您需要规范序列化,其中协议缓冲区消息的编组输出保证随着时间的推移保持稳定。不幸的是,目前不存在规范序列化的规范。您需要自己编写或找到避免需要的方法。

我能找到的最接近的解决方案是deepmind objecthash-proto但过去 4 年没有任何贡献,所以我认为它可能已经过时了

于 2022-01-16T12:07:15.583 回答