go语言中protobuf使用message名字构建PB实例

在使用Protobuf通信或者存储过程中,可能会有这样一个需求,根据PB的message名字来构建一个PB结构的实例,然后再进行反序列化。
举个例子,现在有一个PB:

syntax = "proto3";
option go_package = "./netmsg;netmsg";
package netmsg;

message pbPingPong
{
	uint32 time = 1;
}

序列化成二进制数据后,再根据message名字netmsg.pbPingPong来创建一个PB实例,从而可以对之前序列化的二进制数据进行反序列化。

所有的PB结构类型,都在protoregistry.GlobalTypes有根据名字注册,注意是全名,即包含包路径,比如前面的pbPingPong全名为netmsg.pbPingPong,可以使用proto.MessageName(m Message) protoreflect.FullName函数取得。有了全名,就可以使用protoregistry.GlobalTypes.FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error)获取PB类型,再根据类型构建出PB实例。

下面直接给出源码:

package main

import (
	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/reflect/protoreflect"
	"google.golang.org/protobuf/reflect/protoregistry"
	"server/netmsg"
	"testing"
)

func NewPB(message protoreflect.FullName) (proto.Message, error) {
	name, err := protoregistry.GlobalTypes.FindMessageByName(message)
	if err != nil {
		return nil, err
	}
	return name.New().Interface(), nil
}

func TestPB(t *testing.T) {
	pb := &netmsg.PbPingPong{
		Time: 10,
	}
	data, err := proto.Marshal(pb)
	if err != nil {
		t.Errorf(err.Error())
		return
	}
	name := proto.MessageName(pb)
	newPB, err := NewPB(name)
	if err != nil {
		t.Errorf(err.Error())
		return
	}
	err = proto.Unmarshal(data, newPB)
	if err != nil {
		t.Errorf(err.Error())
		return
	}
	if newPB.(*netmsg.PbPingPong).Time != 10 {
		t.Errorf("time should be equal")
	}
	t.Logf("OK")
}

如果对你有帮助,欢迎点赞收藏!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值