6 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.
- im_dario 3y agoNo "compiler assistance" doesn't mean no assistance at all. There is a growing set of linters based on the community-accepted analysis package [0] that prevent this and other gotchas that Go devs may be prone to. It isn't a perfect solution, but it works at community level without needing to wait for the Go team to take care of or changing the language/toolchain. 0: https://pkg.go.dev/golang.org/x/tools/go/analysis https://pkg.go.dev/golang.org/x/tools/go/analysis
- saturn_vk 3y ago> if you forget Does this happen? Is there any data on how often error checking is forgotten?
- fl0ki 3y agoIn my experience, outright forgetting is very rare because an unused err should be a warning, but the following is not nearly as rare as it should be: if err != nil { return nil } With how boilerplate the correct version is, you learn to skip over it entirely, meaning it can be hard to spot that anything is wrong here. Linters do exist for this now, but they have so many false positives on other error handling cases that most people don't bother with them.
- Conscat 3y agoGoland and Emacs (with Tree Sitter) can at least generate those automatically for you so they won't be forgotten, fwiw.
- 3y ago
- 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.
- 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.
- 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.
- 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?