我完全陷入Go中Protobuf的问题

给出以下代码:

if proto.MessageName(&messages.AddedItemEvent{}) == "" {
    log.Fatal("empty")
}

这将评估为true并退出应用程序。
什么可能会使protobuf在oj​​it_code上返回空字符串?
我可以看到类型和它们的名称已在生成的protobuf消息代码中按需注册:
func init() {
    proto.RegisterType((*AddItemCommand)(nil), "messages.AddItemCommand")
    proto.RegisterType((*AddedItemEvent)(nil), "messages.AddedItemEvent")
    proto.RegisterType((*RenameCommand)(nil), "messages.RenameCommand")
    proto.RegisterType((*RenamedEvent)(nil), "messages.RenamedEvent")
    proto.RegisterType((*DumpCommand)(nil), "messages.DumpCommand")
}

我还验证了上面的MessageName实际上可以运行,并且可以运行。

我还有其他生成的原始消息,它们按预期返回其名称。
那么,这里出了什么问题?

编辑
原始文件看起来像这样
syntax = "proto3";
package messages;

//user messages
message AddItemCommand {
  string item = 1;
}
message AddedItemEvent {
  string item = 1;
}
message RenameCommand {
  string name = 1;
}
message RenamedEvent {
  string name = 1;
}
message DumpCommand {}

重新编辑。
手动调用
proto.RegisterType(((* messages.AddedItemEvent)(nil),“messages.AddedItemEvent”)

init函数开始,使其工作。
所以以某种方式清除了类型注册表在mainmessages.init之间的某个位置

任何人?

最佳答案

不,类型注册表未清除。

很可能您在生成的代码中使用了proto包的不同实现,其中proto包实现的选择由您选择的原始代码生成器解决。在您的代码中,您实际上是在尝试获取MessageName

在go二进制过程的生命周期中,Go中每个导入的包都被精确地初始化了一次。每个已初始化的程序包都有自己的名称表(已导出和未导出)及其对应的值。 proto包尤其维护已知原型(prototype)消息名称和类型的所谓“注册表”。注册表进行了一点简化,它是一种包范围的映射,将消息类型与它们的相应名称相关联。该映射将在程序包初始化时初始化并填充。然后,要检索MessageName,可以通过一些辅助函数间接访问它。关键是,如果您使用在代码,生成的代码或依赖项中导入的不同proto包实现,则有可能在应用程序启动时填充一个注册表,然后尝试从中检索MessageName。其他一些对此一无所知的注册表。经验法则是始终在整个应用程序中使用单一供应商提供的协议(protocol)代码生成器插件,预生成的原型(prototype)类型库和proto包实现。

最受欢迎的proto软件包(我从未使用过或遇到过其他软件包)是https://github.com/golang/protobufhttps://github.com/gogo/protobuf
仔细检查您的协议(protocol)生成器插件和程序包导入,希望一切都很好。

关于go - proto.MessageName返回空字符串,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39712915/

10-12 21:33