7 ms·
The whole point of error handling in go is that magic does not happen. Large error handling frameworks can create tracing difficulties. In the authors example h
by Fin_Code 3y ago
The whole point of error handling in go is that magic does not happen. Large error handling frameworks can create tracing difficulties. In the authors example he will never be confused as to where the error occurred. Is it overly verbose, yes. Do I prefer it yes. I am quickly able to identify and address issues.
- kitkat_new 3y agowell, no magic, goal reached. However, the current implementation of error handling is atrocious. If Go would take sum types and question marks from Rust, Go would keep the general error handling strategy and philosophy with the difference of being way less verbose and more ergonomic.
- nonethewiser 3y ago> If Go would take sum types and question mark Go is an incomplete language masquerading as a simple one.
- riwsky 3y agoFrom “the rise of worse is better”: > Completeness -- the design must cover as many important situations as is practical. All reasonably expected cases should be covered. Completeness can be sacrificed in favor of any other quality. In fact, completeness must be sacrificed whenever implementation simplicity is jeopardized. Consistency can be sacrificed to achieve completeness if simplicity is retained; especially worthless is consistency of interface.
- MobiusHorizons 3y agoI get that you don’t like some of the features go has done without, but how do you justify incomplete? What do you even mean by that word? Clearly lots of code has been written in it. Its deficiencies do not prevent programs from being expressed. The only definition I can think of for complete would be Turing completeness, but that is clearly too low a bar for what you are saying.
- bananapub 3y ago> but how do you justify incomplete are you seriously suggesting that Go's insistence of requiring the programmer to scatter "if err != nil {}" after most function calls - with no compiler assistance if you forget - is complete either in the sense of "having all necessary parts, elements, or steps" or "being finished"? it's terrible, causes bugs and it seems incredibly unlikely to me that it won't be improved.
- Conscat 3y agoGoland and Emacs (with Tree Sitter) can at least generate those automatically for you so they won't be forgotten, fwiw.
- randomdata 3y agoAt very least, unless you hate other developers for some reason, you need to document in your test suite what errors are returned. How, exactly, are going to forget a necessary `if err != nil` without your test suite blowing up? If you do hate other developers for some reason, why not leave out some `err != nil`s to really drive home your hatred towards them?
- kelnos 3y agoIf you can forget to check an error at a call site, then you can just as easily forget to add a proper test for that error condition. I prefer writing in languages where the syntax and standard library and compiler will help me avoid mistakes, and not have to rely on tests -- more error-prone code I have to write! -- to do that for me (and yes, I understand that I will never avoid having to write some tests, but the more the language and compiler can do for me, the better). A language with generics and sum types (so you can implement something like Either, Try, or Result) doesn't let you use the result of a fallible function call without handling the error explicitly. And if the result is unit/void, most compilers/linters will still warn you if you haven't used the Either/Try/Result type that's returned. But ultimately it doesn't matter. Write in whatever language you feel comfortable and most productive. Well, unless you're starting a new security-sensitive project and want to write in C. Just... stop.
- riwsky 3y agoRust-the-language, maybe—but Rust-the-ecosystem makes heavy use of magic crates like `thiserror` and `anyhow`. I’m not saying it’s a better or worse philosophy, but it’s certainly a different philosophy.
- kelnos 3y agothiserror and anyhow exist for ergonomic purposes (and enhance the experience of using the question-mark operator). Libraries shouldn't be leaking thiserror or anyhow types into their public interface. If they are, that's bad design.
- jeremyloy_wt 3y agothiserror and anyhow are hardly magic. The former is just macros for error definition The latter is just a wrapper around box dyn error
- riwsky 3y ago“Magic” isn’t a rigorously defined term, so let’s ignore it. Support for macros is a huge philosophical difference between Rust and Go.
- jeremyloy_wt 3y agoI disagree in the context of error handling. The go ecosystem frequently utilizes `go generate` to handle boilerplate code generation. That’s the exact same way `thiserror` utilizes macros to generate plain error structs. While macros can do more, in this case it’s the same.
- Thaxll 3y agoIt's not atrocious, when you work on Go code on a daily basis it's fine but I agree that it's repetitive. Really an overblown problem from people that don't use Go much tbh. I work with people that used extensivly Java / C# / C++ and it's not the thing they complain about. They usually enjoy the fact that it's not exception based.
- randomdata 3y agoWhile sum types would be a welcome addition in general, summing an error is logically erroneous. It is an independent state. The question mark is interesting, but as the try proposal discovered, how do you solve the leaking problem? That doesn't have a good solution yet.
- valenterry 3y ago> Summing an error is logically erroneous. It is an independent state. Doesn't compute for me. Care to explain?
- wruza 3y agoIn practice it’s either-or in “error handling”, because that’s when you decide what to do and not do next.
- randomdata 3y agoNot true. As zero values are to be useful, one should never have to observe the error state unless the error is significant to the caller for some reason. Sometimes the error is significant. Sometimes it isn't. That depends on what the caller's needs are. Summing the error makes assumptions about the caller that may or may not be true. That is a bad API design.
- mplanchard 3y agoYes this is why you can just operate on the non error value (with map), immediately propagate the error (with ?), just operate on the error value (with map_err), or ignore it completely (eg by converting it to an option or using something like unwrap_or_else). Errors in Rust are still just possibly present values: they’re just wrapped in an interface (a sum type) that forces you to be explicit about your intent to ignore, handle, or propagate the error.
- randomdata 3y agoPropagation suffers from the leaking problem. Rust has solutions for that, but it's not clear how that translates to Go, hence why the "try" proposal failed. I'm sure there is some solution out there, but nobody has come up with a good one. It turns out if nobody does the work, the work doesn't get done. Again, needing to be explicit about your intent to do anything with an error is faulty. The values are not dependent. Just because some languages have gotten it wrong doesn't mean they all should.
- sidlls 3y agoI really appreciate the lack of magic in go's error handling. I do not appreciate the specific implementation of errors in go. It's inefficient (`reflect` is all over the place) and prone to obscuring the actual "error path". In applications of non-trivial size, it also becomes an obstacle to implementing structured logging and other components of observability. This makes debugging/triage of, say, a production incident harder than it needs to be.
- Thaxll 3y agoI've never seen or used reflection with error handling in Go, what do you mean?