今天在使用golang的protoful作为通信消息协议的时候,发现我们必须手动写死消息名称来对应处理消息的func,极为不便,不符合策略模式的设计模式,经过一天的查找最终找到以下解决方法

获取proto Message的全类名

// GetFullNameByMessage 获取pb协议的全类名
func GetFullNameByMessage(msg proto.Message) string {
   reflect := proto.MessageReflect(msg)
   descriptor := reflect.Descriptor()
   name := descriptor.FullName()
   return string(name)
}

根据proto全类名获取Message实例

func GetMessageByFullName(fullName string, data []byte) proto.Message {
	msgName := protoreflect.FullName(fullName)
	msgType, err := protoregistry.GlobalTypes.FindMessageByName(msgName)
	if err != nil {
		logger.Errorf("FindMessageByName err: %v", err)
		return nil
	}
	msg := proto.MessageV1(msgType.New())
	err = proto.Unmarshal(data, msg)
	if err != nil {
		logger.Errorf("proto Unmarshal err: %v", err)
		return nil
	}
	return msg
}
github.com/golang/protobuf
google.golang.org/protobuf/proto
// GetMessageV2ByFullName 根据pb全类名获取消息实例
func GetMessageV2ByFullName(fullName string, data []byte) proto.Message {
	msgName := protoreflect.FullName(fullName)
	msgType, err := protoregistry.GlobalTypes.FindMessageByName(msgName)
	if err != nil {
		logger.Errorf("FindMessageByName err: %v", err)
		return nil
	}
	message := msgType.New().Interface()
	err := proto.Unmarshal(data, message)
	if err != nil {
		return nil
	}
	return message
}