…and now you need to check for nonsense values everywhere, instead of ever being able to know through the type system that you have a meaningful value.
It’s nil pointers all over again, but for your non-pointer types too! Default zero values are yet another own goal that ought to have been thrown away at the design stage.
> instead of ever being able to know through the type system that you have a meaningful value.
That's... not what I'm looking for out of my type system. I'm mostly looking for autocomplete and possibly better perf because the compiler has size information. I really hate having to be a type astronaut when I work in scala.
So, I mean, valid point. And I do cede that point. But it's kind of like telling me that my car doesn't have a bowling alley.
Making an analogy between a car with a bowling alley being as useful as having the ability to know you have a valid selection from a list of choices does not exactly reflect well on your priorities.
I don't really use them that much, so they're superfluous for the most part. Sort of like a car having a bowling alley. I mean, I'll take them if it doesn't complicate the language or impact compile time, but if they're doing to do either of those, I'd rather just leave them.
Adding default branches into the couple of switch statements and a couple spots for custom json parsing that return errors for values outside the set doesn't seem like a bad tradeoff.
I think that's a bad analogy because I actually use ABS and TC. I don't really use an enum heavy style of programming. Maybe twice per project or so. Putting a default branch in a couple switch statements also seems to get me back the same safety (although I'd rather detect the error early and return it in a custom UnmarshalJSON method for the type).
I also imagine I'd use a bowling alley in my car ~2 times per year, tops. So that seems like a better analogy to me.
edit: I guess I should bring up that I don't use go's switch statement much either, and when I do, 99% of the time I'm using the naked switch as more of an analog to lisp's cond clause.
There are still people that swear that they can brake better than ABS. Until they do a side-by-side test.
Re: custom UnmarshalJson implementation - you still have to remember, and do it for every serialized format (e.g. sql).
A default case in a switch only solves, well, switching. If a rogue value comes in, it will go out somewhere. E.g. json to sql or whatever things are moving.
But it does not work. It looks like it would, with the indentation and iota keyword, but its just some variables that do not constrain the type. There will be incoming rogue values, from json or sql or something else.
var g Gender // ok so far.
if err := json.Unmarshal("99", &g); err != nil { panic(err) }
// no error and g is Gender(99)!
Now you must validate, remember to validate, and do it in a thousand little steps in a thousand places.
Go is simple and gets you going fast... but later makes you stop and go back too much.