6 ms·
Struct tags in Go always seemed like a very bad and hacky way to add metadata to fields. I really hope that's something they'll look into in Go 2.
by grenoire 7y ago
Struct tags in Go always seemed like a very bad and hacky way to add metadata to fields. I really hope that's something they'll look into in Go 2.
- seiferteric 7y agoCurrently I am facing an issue where I am unmarshalling json into a protobuf struct. Unfortunately the json tag names are a bit different than the protobuf struct field names. I would love to be able to use struct tags here, but to my knowledge protobuf definitions don't allow this, and I don't think I can put them in after the fact. So I am stuck loading the data into an interface{} and manually pulling out the fields.
- zetetic 7y agois this for the protoc generated code? otherwise, could you not define different struct tags for the different serialization types? type Person { Name string `protobuf:"name",json:"given_name"` }
- seiferteric 7y agoYes it is for the protoc generated code. It would be nice if the protobuf spec allowed for something like tags as well. The main difference is the json coming in uses hyphens, whereas protobuf<->json only allows for underscore or camelCase field names.
- q3k 7y ago> Yes it is for the protoc generated code. It would be nice if the protobuf spec allowed for something like tags as well. Have you seen Protobuf options [1]? They allow for a tag-like-behaviour, but are strongly typed. It's notably used by gogoproto [2] to allow specifying custom field types or names [3] when generating Go stubs. [1] - https://developers.google.com/protocol-buffers/docs/proto#customoptions https://developers.google.com/protocol-buffers/docs/proto#cu... [2] - https://github.com/gogo/protobuf https://github.com/gogo/protobuf [3] - https://godoc.org/github.com/gogo/protobuf/gogoproto https://godoc.org/github.com/gogo/protobuf/gogoproto
- seiferteric 7y agoThanks, I have looked at options. I think it could work, but I think it would require writing a custom marshal/unmarshal function for each protobuf struct, even if they are essentially the same for each one. I will have to take a closer look at the links though.
- seiferteric 7y agogogoproto worked for me, using the moretags extension, thanks for the links!
- everybodyknows 7y agoCode-gen with help of the 'template' library might be a way out of the code repetition.
- LukeShu 7y agoIf you use gogoproto, it includes an extension to the protobuf spec, to override json tag for the emitted Go. https://github.com/gogo/protobuf/blob/master/extensions.md https://github.com/gogo/protobuf/blob/master/extensions.md Use it like: import "github.com/gogo/protobuf/gogoproto/gogo.proto"; ... Type myField = 1 [(gogoproto.jsontag) = "my-field"];
- tynorf 7y agoOne technique I use is to create a struct that mirrors the layout of the target struct, then just cast between them. So if you have a type Person struct { FirstName string `json:"first_name"` } And you get json like `{"name": "Alice"}`, you can decode it something like this: var doc struct { FirstName string `json:"name"` } json.Unmarshal(data, &doc) person := Person(doc) I have not looked at the assembly so I can't say whether this incurs extra overhead or not.
- seiferteric 7y agoI thought of this, but I would have to do this for every single protobuf message. Also, anytime the protobuf changes, you would have to update the code.
- tynorf 7y agoYour protobuf messages are changing that much? My condolences. ETA: Also, you already are needing to add code to every encode/decode point for the `map[string]interface{}` handling. :P
- cle 7y agoI haven’t had any issue with them. I certainly like them better than Java annotations, which encourage way too much black box magic and induce too much code coupling. The fact that they’re a little awkward to use is good, nobody should have to figure out what sort of magic happens with a pile of metadata on a field.
- jayd16 7y agoHow do Java annotations encourage that more than struct tags? If you can write metadata, you can write code that reflects on it. I don't see any structural difference other than IBM hasn't started writing enterprise WebSphere code in Go, yet.
- deleted 7y ago[deleted]
- jayd16 7y agoAre struct tags meant to be similar to Java Attributes and C# Annotations? Seems like a fine pattern but needs more tooling.
- SamWhited 7y agoI don't know about Java or C#, but it's a key-value pair on a struct field that you can get back with reflection.
- azth 7y agoThey're much weaker than annotations and attributes. You can amend the type system with annotations (e.g. nullability detection, as well as compile time validation - check out micronaut to see an example of what they're doing with annotations).