我使用protobuf定义了3种消息类型。 (MsgA,MsgB,MsgC)
Message MsgType {
string type; // indicate MsgA/ MsgB/ MsgC
};
我定义了一个MsgType来指示消息是MsgA / MsgB / MsgC
|MsgType|MsgA/MsgB/MsgC|some end marker|
然后,我生成了一些消息,并以这种格式存储在内存映射文件中:
msgType := &MsgType{}
err := proto.Unmarshal(byteArrayforMsgType, msgType)
...
switch msgType.GetType() {
case "MsgA":
a := &MsgA{}
err := prto.Unmarshal(byteArrayforMsg, a)
...
case "MsgB":
b := &MsgB{}
err := prto.Unmarshal(byteArrayforMsg, b)
...
case "MsgC":
c := &MsgC{}
err := prto.Unmarshal(byteArrayforMsg, c)
...
}
当我从缓冲区读取时,我想做类似的事情:
#define CASE(MsgType)\
case #MsgType:\
msg := createObject<msgType>();\
...
switch type {
CASE(MsgA);
CASE(MsgB);
CASE(MsgC);
}
这是问题: 由于每种情况都非常相似,所以我想做一些类似于C ++的事情
<?php
namespace App\DependencyInjection;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\DependencyInjection\Extension\Extension;
/**
*/
class AppExtension extends Extension
{
/**
* @see Symfony\Component\DependencyInjection\Extension.ExtensionInterface::load()
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../config'));
$loader->load('services.yml');
//$loader->load('parameters.yml');
echo __DIR__.'/../Resources/DataFixtures';
die();
$fixture_loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/DataFixtures'));
$fixture_loader->load('Patients.yml');
$data_loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/datas'));
//$data_loader->load('first_name.yml')
}
}
实际上,有许多消息类型,而不仅仅是A,B,C。每个案例部分都会有重复的代码。 Go中是否有任何方法可以做与C ++类似的事情?
答案 0 :(得分:4)
您可以使用一个映射,其中存储从类型名称(例如MsgType.type
字段)映射的类型描述符。类型描述符可以是reflect.Type
。
因此,您可以通过简单的映射查找来获取类型描述符,并且可以使用reflect.New()
来获取指向该类型的新零值的指针。
例如:
var registry = map[string]reflect.Type{
"MsgA" : reflect.TypeOf(MsgA{}),
"MsgB" : reflect.TypeOf(MsgB{}),
"MsgC" : reflect.TypeOf(MsgC{}),
}
阅读消息时的常用代码:
typeToRead := registry[msgType.GetType()]
msg := reflect.New(typeToRead).Interface()
err := prto.Unmarshal(byteArrayforMsg, msg.(proto.Message))
注意:msg
的类型为静态interface{}
,它包装了指向您的一种消息类型的指针,例如存储在其中的具体值的类型可能是*MsgA
,正是您必须传递给proto.Unmarshal()
的内容。
获取新消息值的另一种方法可能是使用构造函数,因此不需要进行反射。
它是这样的:
var registry = map[string]func() proto.Message{
"MsgA" : func() proto.Message { return new(MsgA) },
"MsgB" : func() proto.Message { return new(MsgB) },
"MsgC" : func() proto.Message { return new(MsgC) },
}
并使用它:
creator := registry[msgType.GetType()]
msg := creator()
err := prto.Unmarshal(byteArrayforMsg, msg)