我完全陷入Go中Protobuf的问题
给出以下代码:
if proto.MessageName(&messages.AddedItemEvent{}) == "" {
log.Fatal("empty")
}
这将评估为
true
并退出应用程序。什么可能会使protobuf在ojit_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
函数开始,使其工作。所以以某种方式清除了类型注册表在
main
和messages.init
之间的某个位置任何人?
最佳答案
不,类型注册表未清除。
很可能您在生成的代码中使用了proto
包的不同实现,其中proto
包实现的选择由您选择的原始代码生成器解决。在您的代码中,您实际上是在尝试获取MessageName
。
在go二进制过程的生命周期中,Go中每个导入的包都被精确地初始化了一次。每个已初始化的程序包都有自己的名称表(已导出和未导出)及其对应的值。 proto
包尤其维护已知原型(prototype)消息名称和类型的所谓“注册表”。注册表进行了一点简化,它是一种包范围的映射,将消息类型与它们的相应名称相关联。该映射将在程序包初始化时初始化并填充。然后,要检索MessageName
,可以通过一些辅助函数间接访问它。关键是,如果您使用在代码,生成的代码或依赖项中导入的不同proto
包实现,则有可能在应用程序启动时填充一个注册表,然后尝试从中检索MessageName
。其他一些对此一无所知的注册表。经验法则是始终在整个应用程序中使用单一供应商提供的协议(protocol)代码生成器插件,预生成的原型(prototype)类型库和proto
包实现。
最受欢迎的proto
软件包(我从未使用过或遇到过其他软件包)是https://github.com/golang/protobuf和https://github.com/gogo/protobuf。
仔细检查您的协议(protocol)生成器插件和程序包导入,希望一切都很好。
关于go - proto.MessageName返回空字符串,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39712915/