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