4 ms·
I like the simplicity and how opinionated Go is. There's typically one way to do things and that's incredibly useful. But lack of real enums for me falls into
by cletus 4y ago
I like the simplicity and how opinionated Go is. There's typically one way to do things and that's incredibly useful.
But lack of real enums for me falls into the "How is this a thing?" bucket.
Like Java introduced what are (IMHO) a pretty good enum almost 20 years ago. Java enums are classes, basically. They can have state and methods. Super-useful.
I like Hack but Hack's enums are a little weird in the sense that you have a bit of an odd syntax to indicate if automatic coercion is allowed.
I like the idea in this post as being better than straight strings or ints but there are still 2 downsides:
1. As a variable (not a constant) it gives the compiler less options on how this can be optimized; and
2. (This is the big one) One of the best things about enums is using them in switch statements such that adding a new value will cause a compiler error (assuming you don't use a default branch, which should be discouraged for this).
Rust enums and match expressions, for example, cover all of this.
- cube2222 4y agoNot that it's a great solution, but there's https://github.com/BurntSushi/go-sumtype https://github.com/BurntSushi/go-sumtype for (2).
- majewsky 4y agoThese sumtypes don't mesh well with JSON/YAML/etc. serialization though. If you have type MySumType interface { sealed() } like in the code example for go-sumtype, serialization is easy enough: type MySumType interface { json.Marshaler sealed() } But deserialization runs into a roadblock, because you cannot implement interfaces like json.Unmarshaler on an interface type. Something like type MySumType interface { json.Marshaler json.Unmarshaler sealed() } will not work: Given `var s MySumType`, json.Unmarshal() will croak because it cannot call UnmarshalJSON without knowing the concrete type of `s`. So for deserialization, you'd need an extra wrapper type that provides the json.Unmarshaler implementation.
- catlifeonmars 4y ago> But deserialization runs into a roadblock, because you cannot implement interfaces like json.Unmarshaler on an interface type. In addition to introducing the wrapper type, this could also be fixed by using a JSON decoder implementation that supports type/location hooks. In other words, this is more of a limitation of the custom unmarshaling mechanism chosen by the builtin encoding/json package.
- masklinn 4y ago> So for deserialization, you'd need an extra wrapper type that provides the json.Unmarshaler implementation. You'll probably need something along those lines either way, for the simple reason that there is no single mapping between sum types and JSON (or equivalent / similar) For instance serde provides 3 different serialisation schemes, and once in a while you still need a bespoke deserialiser.
- Splizard 4y agoRight, the builtin switch statement is not exhaustive but you can quite easily create a Switch method on your enum type in Go 1.18+ that is exhaustive.