Comment by madeofpalk
18 hours ago
I'm actually not all that fussed about Result or Option types. I don't mind Go's approach to error handling. I think it should just have language/analysis features built it to ensure that you do it 'correctly', so things don't blow up if you do not remember a part of the system ("this value is sometimes nil") or you forget to do something.
The fact that external tools exist that "every Go project tends to use" to fill common a gap in the type system indicates to me that maybe the language itself could be improved.
You rarely get anything for free.
Look at exceptions in Java, for instance. In theory the mechanism is there to guarantee that errors will be handled. In practice there are multiple schools of thought — several of which purposefully circumvent this mechanism by throwing runtime exceptions because they think checked exceptions just leads to a lot of unnecessary work.
It has been too long since I used Java to remember all the arguments for and against. But I do remember trying multiple approaches and realizing that only using checked exceptions turned out to be a bit too inflexible. That there were legitimate reasons to use runtime exceptions.
Go’s type system is probably “good enough”. Sure, I’d love to have option types and results. And it would have been nice to move some of the things in vet, lint, staticcheck into the compiler. But in _practice_ separating them is actually beneficial. Because it allows you to trade build speed for security. For instance when you are making a tiny change and you just want to make sure it still builds. That’s a _practical_ tradeoff you could not have made if the compiler were always strict.
One thing I wish Go would have adopted is Javadoc-like comments with explicit markup to document parameters, return values and possibly panics. Those were _more_ useful in practice than exceptions in Java because you could force people to be more deliberate when designing “contracts”. When I did Java we used to have the build fail if classes and methods did not document all params, return values, exceptions etc.
I also taught people to write unit tests while _only_ looking at the Javadoc for what they were testing and notating at the code. Even after years of doing this, I’d regularly find that implementations didn’t behave as documented when writing tests. This made people care about interfaces/seams/APIs/contracts and spend less time obsessing over having the compiler save them from sloppiness. It put the developer in the driving seat rather than have them run behind the compiler and just nudging things into a state where it compiles. It helped people think more about why something failed from a design point of view rather than put all their faith in the tooling.
I think that’s the biggest mistake of Go: it doesn’t care about documentation and to the extent it does, it introduces really, really stupid, pointless formal rules that does nothing to help developers.