proto.MessageName 返回空字符串
Posted
技术标签:
【中文标题】proto.MessageName 返回空字符串【英文标题】:proto.MessageName returns empty string 【发布时间】:2016-09-26 21:44:41 【问题描述】:我完全被 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
确实可以运行,并且确实可以运行。
我还有其他生成的原始消息,它们按预期返回它们的名称。 那么这里出了什么问题呢?
编辑 原型文件是这样的
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
之间的某个地方被清除了
有人吗?
【问题讨论】:
我找到了这个原因,我的一些代码使用了真正的google protobuf lib,一些使用了gogo protobuf lib。相同的 api,不同的状态存储... 【参考方案1】:不,类型注册表未清除。
很可能您在生成的代码中使用了不同的proto
包实现,其中proto
包实现选择由您选择的原型代码生成器解决。在您的代码中,您实际上是在尝试获取 MessageName
。
在 Go 二进制进程的生命周期中,Go 中的每个导入包都会被初始化一次。每个初始化的包都有自己的名称表(导出和未导出)及其对应的值。 proto
包特别维护所谓的已知原始消息名称和类型的“注册表”。稍微简化一下,registry 是一个包范围的映射,将消息类型与其对应的名称相关联。此映射在包初始化时被初始化和填充。然后,要检索MessageName
,您可以通过一些辅助函数间接访问它。关键点是,如果您在代码、生成的代码或依赖项中使用不同的 proto
包实现,那么很有可能,在应用程序启动时您填充一个注册表,然后您尝试检索MessageName
来自其他一些对此一无所知的注册表。经验法则是始终使用来自单个供应商的 protoc 代码生成器插件、预生成的原型类型库和 proto
包实现。
最流行的proto
包(我从未使用过或遇到过任何其他包)是https://github.com/golang/protobuf 和https://github.com/gogo/protobuf。
仔细检查您的 protoc 生成器插件和包导入,我希望一切都好。
【讨论】:
以上是关于proto.MessageName 返回空字符串的主要内容,如果未能解决你的问题,请参考以下文章
stringByEvaluatingJavaScriptFromString 返回空字符串,但在 Safari 中返回完整字符串