7 ms·
Go really blew me away with its explicit error handling. As someone who has come from the OOP cult of clean code and other useless principles that haven’t led o
by devjab 2y ago
Go really blew me away with its explicit error handling. As someone who has come from the OOP cult of clean code and other useless principles that haven’t led our industry to have less messes over the past 20-30 years. Who was slowly moving into the “simplicity”, “build things that can be easily deleted”, “YAGNI” mindset it simply clicked.
Then Rust took it a few levels beyond Go.
It’s a really good list, I suspect the languages you add is going to spend on your experience. So I wouldn’t feel too sad if your favorite language is on that list. The author lists Java as a language with an amazing standard library, but something tells me a lot of people will have C#, Go or similar as their Java, and that’s fine!
- scubbo 2y agoI'm still convinced that Rust does it _right_ by allowing you to "chain through" errors using `Result`. Having to pepper `if err != nil { return ..., err}` repeatedly into your code is just distracting from the core logic - 99% of the time, that's the response anyway, so being able to just write your happy-case logic and have an implicit "but if there are any errors, return them immediately" (but still returned as a value rather than thrown as an orthogonal Exception) is the best of both worlds.
- ChadNauseam 2y agoIt is really great. I just wish there was a better story for combining error types. thiserror works, but it’s annoying boilerplate to have to write imo.
- marcosdumay 2y agoWhen you require that your "algebraic" types always be tagged, so that `type X = A + B` and `type Y = A + B` are always different, you lose most of your capacity of seamlessly composing the types. In other words, Rust doesn't have a type that means "either IO Error or Network Error", so it can't just compose those two behind the scenes into something that you can later decompose. You have to create some tag, and tell the compiler how to apply the tag, because each tag is different.
- elcritch 2y agoThat’s a good way to put it. Lots about Rust is great, but the lack of anonymous union types over complicates a lot of problems. The trait system would be much less of a headache if you could define a local child types as well.
- treyd 2y agoThe anyhow crate complements thiserror pretty well in my experience. I use it "top-down" facing where individual errors in any component are defined with thiserror, but then we bubble them up by wrapping them in a `anyhow::Error` if we don't know what to do with them. It also has the nice thing of being able to produce simplified stack traces to help diagnose where things are going wrong. And then you can downcast to component-level thiserror Errors if you want to inspect something closely from high up.
- jasongill 2y agoI have been using Golang recently and have the exact opposite feeling about it, which is likely due to my limited exposure to it. Needing to constantly check if a specific return value is not nil just seems so sloppy but I have yet to come across a "better" way as it appears to just be a Golang convention. Is there a good post about better ways to handle errors in Go?
- devjab 2y agoThis is the better way as far as I’m concerned. Go has a philosophy to be simple, and this is explicit error handling at its simplest. You deal with errors exactly where they occur. I think a lot of people simply prefer implicit error handling and long exception chains. There is nothing wrong with that but that’s not how Go does error handling. After a couple of decades in the industry I really prefer explicit error handling because while powerful implicit error handling is also easy to get wrong. Which means I have to go through ridiculous chains of exceptions to find some error someone introduced years ago, instead of being able of heading directly to it and immediately understanding what is going on. So I guess it’s a little contradictory that I prefer the Rust approach, but I think the compromise of added complexity is small enough to make up for the added safety and “manoeuvrability”. The flip-side is of course that Go’s simplicity is part of the reason it’s seeing a lot of adoption while most other “new” languages aren’t. (Depending on where you live).
- treflop 2y agoI prefer implicit error handling if exceptions are checked and defined as part of the contract, otherwise it’s definitely hard to trace. I know the biggest complaint with checked exceptions is that people tend to just use catch all exceptions, but that’s just sloppy work. If they’re a junior, that’s when you teach them. Otherwise, people who do sloppy work are just sloppy everywhere anyway.
- devjab 2y agoMy issue with a lot of the best practice principles in SWE is that they were written for a perfect world. Even the best developers are going to do sloppy work on a Thursday afternoon after a day of shitty meetings during a week of almost no sleep because their babies were crying. Then there are there times when people have to cut corners because the business demands it. A million little things like that, which eventually leads to code bases which people like Uncle Bob will tell you were made by people who “misunderstood” the principles. Simplicity works because it’s made for the real world. As I said I personally think Rust did it better, but if you asked me to come help a company fix a codebase I’d rather do it for a Go one than Rust.
- BrandoElFollito 2y agoComing from Python, as an amateur dev, error handling in Go was annoying as hell. But I had no other choice so I went for it. Afer a few programs I realized I never really thought about error handling - Go forces you to decide where you want to handle your error, where to inform about it etc. It is still annoying (especially the boilerplate) but it had a net positive value for me in terms of learning.