登录
首页 >  Golang >  Go问答

自定义 protobuf 选项用于 Go 中的 Any 类型消息

来源:stackoverflow

时间:2024-02-24 15:00:24 147浏览 收藏

你在学习Golang相关的知识吗?本文《自定义 protobuf 选项用于 Go 中的 Any 类型消息》,主要介绍的内容就涉及到,如果你想提升自己的开发能力,就不要错过这篇文章,大家要知道编程理论基础和实战操作都是不可或缺的哦!

问题内容

我有一个 grpc 服务定义如下:

message sendeventrequest {
  string producer = 1;
  google.protobuf.any event = 2;
}

message sendeventresponse {
  string event_name = 1;
  string status = 2;
}

service eventservice {
  rpc send(sendeventrequest) returns (sendeventresponse);
}

我还定义了一个自定义消息选项:

extend google.protobuf.messageoptions {
  // event_name is the unique name of the event sent by the clients
  string event_name = 50000;
}

我想要实现的是让客户端创建自定义原型消息,将 event_name 选项设置为“常量”。例如:

message somecustomevent {
  option (mypackage.event_name) = "some_custom_event";

  string data = 1;
  ...
}

这样服务就可以跟踪正在发送的事件。当我执行类似的操作时,我可以从特定的 proto.message 获取选项的值:

_, md := descriptor.MessageDescriptorProto(SomeCustomEvent)
mOpts := md.GetOptions()
eventName := proto.GetExtension(mOpts, mypackage.E_EventName)

但是,当消息类型为 github.com/golang/protobuf/ptypes/any.any 时,选项为零。如何从消息中检索 event_name?我遇到过 protoregistry.messagetyperesolver,它看起来可能有所帮助,但我需要找到一种方法来在客户端集成时动态更新事件的原型定义。


解决方案


为了获取 any 类型的选项,您需要其特定的 protoreflect.messagetype 以便您可以将其解组为特定消息。为了获取消息类型,您需要一个 messagetyperesolver

any 包含 type_url 字段,可用于此目的。为了将 any 对象解组为现有消息类型的消息:

// globaltypes contains information about the proto message types
var res protoregistry.messagetyperesolver = protoregistry.globaltypes
typeurl := anyobject.gettypeurl()
msgtype, _ := res.findmessagebyurl(typeurl)

msg := msgtype.new().interface()
unmarshaloptions := proto.unmarshaloptions{resolver: res}
unmarshaloptions.unmarshal(anyobject.getvalue(), msg)

收到特定消息后,您可以简单地获取您需要的选项:

msgopts := msg.protoreflect().descriptor().options()
eventname := proto.getextension(msgopts, mypackage.e_eventname)

请注意,如果消息未扩展 event_name 选项,proto.getextension 将会出现混乱,并且需要恢复。该块可以添加到函数的开头:

defer func() {
    if r := recover(); r != nil {
        // err is a named return parameter of the outer function
        err = fmt.Errorf("recovering from panic while extracting event_name from proto message: %s", r)
    }
}()

编辑:请注意,应用程序必须导入包含原型定义的包,以便 protoregistry.globaltypes 识别该类型。您可以在代码中执行类似的操作:

var _ mypackage.someevent

go 中的 any.ANY 类型包含 typeurl 字段,该字段包含已发送消息的类型。然后,您可以使用 UnmarshalAny 来生成正确的 go 类型。

链接到 complete guide,了解如何使用 any.ani

今天关于《自定义 protobuf 选项用于 Go 中的 Any 类型消息》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于的内容请关注golang学习网公众号!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>