from sxan@midwest.social to golang@programming.dev on 20 Dec 02:26
https://midwest.social/post/20651402
I have a situation where generics would be useful: a server (that I do not control or influence) with many API endpoints that each returns very similar json. There’s an envelope with common attributes and then an embedded named substructure (the name differs in the return value of each call) of a different type.
Without generics, you could do something like:
type Base struct { // common fields } type A { Base A struct { // subtype fields } } type B { Base B struct { // subtype fields } }
but then you’d need to either duplicate a bunch of API calling and unmarshalling code, or consolidate it and do a bunch of type casting and checking.
Generics to the rescue: subtypes become specific types for a general type:
type Base[T any] { // common fields Subfield T } type A struct { // subtype fields } type B struct { // subtype fields }
It even looks cleaner! Ah, but the rub is that the marshaled field name Subfield
is the same for every type: there’s no way to specify a tag for a struct type so that Subfield
is un/marshaled with a name specific to the type.
The only thing I can think of is to create a custom unmarshaller for Base
and use introspection to handle the specific type.
Am I missing a less hacky (introspection is always hacky) way to set a default tag for any field of a given struct type? How would you do this?
This pattern - APIs using envelopes for data packets - is exceedingly common. I can’t believe the only way to solve it on Go is by either mass code duplication, or introspection.
#golang
threaded - newest
I don’t know the Go answer, but this problem exists in other languages and platforms. It can be incredibly annoying when the http client library doesn’t support unwrapping, even with generics.
If you need the subfield to have a name based on the type, you’re going to need introspection / code generation.