-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
protoc-gen-go: generate MarshalBinary/UnmarshalBinary methods for messages #210
Comments
Hi, may we get more information about the use case for this? The |
Wow, thanks for the prompt reply.
This way it takes a model that somehow serialize to a binary format and the function does not have to worry about how this is done. Further the storage-package doesn't have any dependency on the Currently, I'm using Protocol Buffers for the models and manually implement the |
Just wondering, wouldn't
And under the hood, I'm not opposed to adding |
I agree that this would work on 90% of the use cases. But what if I have a model that should serialize all of it's fields, except it's To me it's seem like a better design if a My other argument is, that I find
a bit more expressive. I can tell what's going to happend just by looking at the function's signature. If I think implicit implemented interfaces is the most powerful feature of Go and as a consequence the stdlib-interfaces became kind of a common language for libraries. |
I think there's a valid use case for add |
Great! Thanks for considering the proposal. This would help me a lot. I've started to implement some helpers for BoltDB that implement such interfaces: https://github.com/simia-tech/boltx |
To provide further motivation for this 4.5-year-old feature request, Note that I am not suggesting that messages should also implement |
This would also benefit Go-Redis, which relies on |
Came here for the go-redis usecase. We're caching grpc responses in the raw and this would save us some boilerplate code. Alternatively this could be done trivially w/ a protoc plugin, like this one that implement the encoding/json iface: https://github.com/mitchellh/protoc-gen-go-json |
Is this just waiting for a PR, or does an official decision need to be reached? |
I went ahead and mailed a commit to add this, open to feedback, but it's pretty simple |
Please keep in mind that those methods can easily be provided by an extra protoc plugin and may also provide a different a binary serialisation that isn't compatible with proto3 wire format at all. That would also allow steering via extra options designed for that usecase (e.g. declaring password immission as mentioned above). Thinking further by relying on encoding.MarshalBinary for protobuf, encoding may accidentally generate a binary serialisation that isn't compatible with the wire format or accidentally omit valuable data like the password in aboves example. So I am not sure that is needed for the task of generating models usable for protobuf serialisation/deserialisation. So I have a hard time understanding why that change is in the scope of this tool. |
I would strongly suggest that this be performed by an additional protoc plugin, rather than working it into the official library. As mentioned in the review of the change request, “The problem is that this leads to a non-trivial binary size increase.” |
This adds a dependency on the This could also break existing code that depends on these methods not existing. I'm not sure how plausible that is. Neither point is necessarily an argument against the change, but something to consider. You could probably use |
the main problem of I wish I had like
|
Would the new BinaryAppender interface from Go 1.24 help here? |
It doesn't cover the cases with reallocation. Having io.Writer allows you to keep control over the underlying buffer PS probably better to name it BinaryMarshalerWriter |
Note by the way that there is a cost to generating these methods, in that it messes with the compiler's ability to do dead-code elimination, as it is very difficult for the compiler to prove that a given type that could be used as that interface isn't. In this case, the functions in question are tiny so it I wouldn't think it would be a real problem. There is a workaround here for those that need this functionality now. One can always write e.g. func (m *Model) MarshalBinary() ([]byte, error) {
return proto.Marshal(m)
}
func (m *Model) UnmarshalBinary(data []byte) error {
return proto.Unmarshal(data, m)
} into a sibling file in the same package as the generated code, since go doesn't require every method on a type to be defined in the same file. It's a bit of a PITA if you require this of all of your messages, however. Footnotes
|
seems you didnt get the idea. it is not about the writing to file/socket I've created proposal for the will see... |
If the generated code would include the methods
MarshalBinary
andUnmarshalBinary
from Go's stdlib, the corresponding interfaces from theencoding
package would be satisfied. Storage/Transmitting-Code could be unified and a dependency to the protobuf package could be removed. The methods would look like:The text was updated successfully, but these errors were encountered: