Reputation: 23214
I'm completely stuck on a problem with Protobuf in Go
Given the following bit of code:
if proto.MessageName(&messages.AddedItemEvent{}) == "" {
log.Fatal("empty")
}
This will evaluate to true
and exit the application.
What can possibly make protobuf return empty string on MessageName
?
I can see that the types and their names are registered as they should in the generated protobuf message code:
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")
}
I have also verified that the above init
actually runs, and it does.
I have other generated proto messages, which returns their names as expected. So what is going wrong here?
Edit The protofile looks like this
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 {}
Edit again. Manually calling proto.RegisterType((*messages.AddedItemEvent)(nil), "messages.AddedItemEvent")
From the main
func, makes it work.
So somehow the type registry is cleared somewhere between the messages.init
and main
Anyone?
Upvotes: 3
Views: 2005
Reputation: 11
No, type registry isn't cleared.
Most probably you are using different implementations of proto
package in your generated code, where proto
package implementation choice is addressed by your proto code generator of choice. In your code you are actually trying to get MessageName
.
Each imported package in Go is initialized exactly one time during the go binary process lifetime. Each initialized package has it's own table of names (both exported and unexported) and their corresponding values. proto
package in particular maintains so called "registry" of known proto message names and types. A bit simplified, registry is a package-scoped map associating message types with their corresponding names. This map is initialized and populated on package initialization. Then, to retrieve MessageName
you access it indirectly through some helper function. The key point is, if you use different proto
package implementations imported in your code, your generated code, or in your dependencies, then chances are, on app start you populate one registry, and then later on, you are trying to retrieve MessageName
from some other registry that know nothing about it. The rule of thumb is to always use protoc code generator plugin, pregenerated proto type libraries, and proto
package implementation from a single vendor through out your app.
Most popular proto
packages (I've never used or encountered any other) are https://github.com/golang/protobuf and https://github.com/gogo/protobuf.
Double check your protoc generator plugin and package imports and I hope it'll be all fine.
Upvotes: 1