任何带有 grpc 的字段总是为零

我正在将gRPC与戈朗一起使用。我有一个非常简单的原型定义和一个gRPC服务。原始定义在谷歌/原型布夫/任何类型的认可中有一个字段。gRPC 服务无法将此字段映射到输入值,并且始终初始化为零


原型定义:


syntax = "proto3";


option go_package = "service";

option java_multiple_files = true;

option java_package = "io.grpc.consensus";


import "google/protobuf/any.proto";


package service;


service MyService {

  rpc Verify (Payload) returns (Response) {}

}


message Response {

  string policyId =1;

  string txnId =2;

}


message Endorsement {

  string endorserId=1;

  // This is being initialise to nil by gRPC

  google.protobuf.Any data = 2;

  string signature=3;

  bool isVerified=4;

}



message Payload {

  string policyId =1;

  string txnId =2;

  repeated Endorsement endorsements=3;

}

使用这个,一个简单的gRPC服务被实现:


package service


import (

    "log"


    "golang.org/x/net/context"

)


type ServiceServerImpl struct {

}


func NewServiceServerImpl() *ServiceServerImpl {

    return &ServiceServerImpl{}

}


func (s *ServiceServerImpl) Verify(ctx context.Context, txnPayload *Payload) (*Response, error) {

    log.Printf("Got verification request: %s", txnPayload.TxnId)

    for _, endorsement := range txnPayload.Endorsements {

        j, err := endorsement.Data.UnmarshalNew()

        if err != nil {

            log.Print("Error while unmarshaling the endorsement")

        }

        if j==nil {

       //This gets printed as payload's endorsement data is always null for google/protobuf/any type

            log.Print("Data is null for endorsement")

        }

    }

    return &Response{TxnId: txnPayload.TxnId,  PolicyId: txnPayload.PolicyId}, nil

}

输入数据:


{

  "policyId": "9dd97b1e-b76f-4c49-b067-22143c954e75",

  "txnId": "231-4dc0-8e54-58231df6f0ce",

  "endorsements": [

    {

      "endorserId": "67e1dfbd-1716-4d91-94ec-83dde64e4b80",

      "data": {

        "type": "issueTx",

        "userId": 1,

        "transaction": {

            "amount": 10123.50

        }

    },

      "signature": "MEUCIBkooxG2uFZeSEeaf5Xh5hWLxcKGMxCZzfnPshOh22y2AiEAwVLAaGhccUv8UhgC291qNWtxrGawX2pPsI7UUA/7QLM=",

      "isVerified": false

    }

  ]

}

素胚勾勒不出你
浏览 153回答 2
2回答

月关宝盒

如您所知,是消息类型,因此当您没有为其设置任何值时,它将为零。google.protobuf.Any您必须使用您的结构取消封送数据,请参阅下面来自 protobuf 示例的代码      // marshal any      foo := &pb.Foo{...}      any, err := anypb.New(foo)      if err != nil {        ...      }      // unmarshal any       foo := &pb.Foo{}      if err := any.UnmarshalTo(foo); err != nil {        ...      }或者我认为你可以用它与指针接口(&接口{})一起使用,如下所示:      d := &interface{}{}      if err := endorsement.Data.UnmarshalTo(d); err != nil {        ...      }

qq_笑_17

从软件包1 文档取消编组任何:UnmarshalNew使用全局类型注册表解析消息类型,并构造该消息的新实例以取消编组。为了使消息类型显示在全局注册表中,必须将表示该 protobuf 消息类型的 Go 类型链接到 Go 二进制文件中。对于由原始生成生成的消息,这是通过导入表示 .proto 文件的生成的 Go 包来实现的。注册表的类型为 。类型查找是使用字段完成的,该字段在封送原始消息时由 gRPC 客户端设置为具体类型的 url。protoregistry.GlobalTypesAny.TypeUrl令人困惑的细节是,它可以是任何原始缓冲区消息,但该原始缓冲区消息必须在某个地方定义。Any您的文件没有与输入中的对象匹配的消息定义。可能是此消息在其他地方定义(不在您自己的原型文件中),但无论如何,您都必须导入生成的消息所在的Go包。.protodataData否则,如果输入不是来自已定义的原型消息,您可以自己向原型添加消息定义,然后使用 UnmarshalTo:// proto filemessage Data {    string type = 1;    int user_id = 2;    Transaction transaction = 3;}message Transaction {    float amount = 1;}然后:    for _, endorsement := range txnPayload.Endorsements {        data := generated.Data{}        err := endorsement.Data.UnmarshalTo(&data)        if err != nil {            log.Print("Error while unmarshaling the endorsement")        }    }如果您只需要任意的字节序列,即真正未知的类型,请使用原型类型并将其视为 JSON 有效负载。bytes将其建模为 Go 结构:type Data struct {    Type     string `json:"type"`    UserID   int    `json:"userId"`    Transaction struct{        Amount float64 `json:"amount"`    } `json:"transaction"`}或者,如果客户可以发送任何东西。map[string]interface{}然后在您的处理程序功能中:    for _, endorsement := range txnPayload.Endorsements {        data := Data{} // or `map[string]interface{}`        err := json.Unmarshal(endorsement.Data, &data)        if err != nil {            log.Print("Error while unmarshaling the endorsement")        }    }
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go