Every time this completely tired and worn out take is regurgitated on this website, it reminds me that people write big fat try/catch blocks because they never expect things like file reads to fail.
Though at least Java people doing that get a stack trace, so they can find out which attempt failed. In random Go code you're fairly likely to get "error: file not found" and literally no other info.
Well, the Go's FileNotFound errors returned from the standard library do have the file name in the message string. Java's FileNotFoundException exceptions, on the other hand, don't; and the stacktrace is usually useless because it doesn't record the values of the local variable anyhow.
yeah, the inconsistency there in both standard libraries is... strange to say the least. more info is more gooder IMO, the runtime cost is SO much lower than the troubleshooting cost.
Please be respectful, nobody is regurgitating anything. People are frustrated because half of their programs are if err != nil { return nil, somestruct{}, false, "", err }
I've written several hundred thousands of lines of Go at this point, and the error handling mechanics have never bothered me. There are two things that bother me about errors; error messages that don't capture enough detail to reproduce the situation (user ids, for loop iterator, etc.; you don't get these in stack traces either), and people that discard one error to return another one (i.e. a blind defer x.Close()). With go 1.20, I have one less concern. If that makes you mad, I feel like these people that smugly reply "touch grass" are on to something.
Most exceptions in Java are checked so you choose to either explicitly handle them at the point they are thrown, group them with other exceptions or ignore them completely and let the entire program fail.
> they never expect things like file reads to fail.
They not only expect file reads to fail, they also expect stack overflows, out of memory etc etc. and a lot more. They also know that, more often than not, the place where something fails is not the place where you have enough information to recover properly.
Go's error handling isn't bad because there are checks everywhere: that's probably the only good thing about errors in go. It's bad because the standard library packages for dealing with errors are inefficient. And they're inefficient because of all the reflection and ceremony around understanding what an error actually is at the point in the code where it's most meaningful to inspect it. Any type can become a Go error value by implementing `Error`: but wrapping, unwrapping, and understanding what the error is at a point in the code are all extremely cumbersome and inefficient processes.
Exceptions are objectively better in every way (especially checked exceptions, which would definitely deserve a second chance!)
You get as small/large-grained handling as you need, get sane default behavior (bubbling up to a place where you can actually handle that error), and stack-traces, while you never accidentally overlook a potential failing call (will the 100th if err 3 liner properly handle the error case or just make your code continue to run in a no longer valid state?).
Are you really claiming this under a goddamn Go thread where every third line is error handling?
> Do not survive network boundaries
Well, depends on what you mean here. Do you mean something like RPC? Because there are implementations that can throw an exception for that. I fail to see how is it different with returning an error value, that doesn’t survive network boundaries in itself either.
I fail to come up with any example where exceptions are worse than error return types in the context of threads.
come on, exceptions give you a stack trace with the whole history of what got called from where. How is that worse than your “file missing” error without any explanation?
> easy to ignore
Checked exceptions are a thing. But it is enough to handle them higher up and it will be handled one way or another, while it is much easier to simply fail to handle an err.
> in practice, rarely handled
I can just as well claim that go-style error handling is more often then not not handling properly the issue at hand, and is most definitely not tested for the error case. A bubbled up exception stopping the program/at least a given thread handling a request is a much better outcome then silent failure.
> poor quality messages
They get as high or low quality messages as one wants. I prefer a proper stacktrace with line numbers over a single obscure line I might occasionally be able to debug by grepping a code base.
I’m not talking about exceptions in theory, which you are completely right about. I’m talking about how exceptions are actually used in practice. You can claim “they should do it differently” but I think you would be ignoring that the design of exceptions is the reason they are not handled/networked/etc. I could go into more detail about your points and it might be interesting, but I am drunk.
EDIT: re the noise point, I’m talking about the actual exception when it is read by a developer in a debugging context, not the lines of code dedicated to processing it.