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.initmain之间的某个地方被清除了

有人吗?

【问题讨论】:

我找到了这个原因,我的一些代码使用了真正的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 返回空字符串的主要内容,如果未能解决你的问题,请参考以下文章

unity替换按键转字符返回值

stringByEvaluatingJavaScriptFromString 返回空字符串,但在 Safari 中返回完整字符串

如何从函数中返回字符串

为啥返回字符串的 VB.Net 函数实际上只返回一个字符?

如何创建 3 个简单的函数来返回孤立的字符、返回重复的字符并返回删除了#comment 的字符串?

OpenFileDialog 在超过 260 个字符的路径上返回空字符串(或根本不返回)