_ = f.Close()
... in order to explicitly ignore the error would be nicer, but then, there are many functions which are known to never be checked for their errors, like fmt.Println. That's why the typical advice is to use errcheck, which has filters to avoid "false"-positives (I am not convinced that some function never should be checked for errors).In Java println is checked for errors, as it should be. Every Java program that does println either aborts or deals with the error in some way.
It matters. Take any program that writes to stdout and run it with ">&-" to close stdout. Because of unix, the next file it opens will be file descriptor 1 and the program will start writing the console output to the file. You want the program to abort instead of trashing a file, and especially not to trash /etc/passwd.
That's why you don't want to ignore errors, because any time you do there can be unintended and hard to imagine consequences -- even something as simple as writing to the console. Simply put, Go encourages buggy programs with poor error handling.
What "next file it opens" are you talking about exactly? How does what you're describing work?
Example:
#include <stdio.h>
int main(int argc, char **argv) {
printf("first message\n");
fflush(stdout);
fopen("output", "w");
printf("second message\n");
fflush(stdout);
}
Output: # ./a.out
first message
second message
# ./a.out 1>&-
# cat output
second message
By ignoring the error, the program continued on and then wrote console output messages to the file after it was opened. There have been exploits due to this bug, but the real point is that you could never predict this failure without good knowledge of unix and careful consideration. This is why error codes should not be cavalierly ignored, because it's really hard to know what might happen if you do.Last I checked, Go operates the same way as this C example. Java fails on the "first message" if stdout is closed so it doesn't trash the file, not because they even specifically thought of this scenario but just because errors are not ignored by default and are not easy to ignore.
I frankly don't see how this is OK, nor better. Errors are real in the sense that they are evidence that the programmer's mental model of state did not line up with the actual state (usually in some corner case). There is literally NO circumstance in which being in a programmer-unknown state (yet still "alive" so to speak) is better than being in a programmer-known-and-accounted-for state. (For an example of being in a programmer-unknown yet alive state, see: Every Security Hole Ever.) This is why "throwing" is appropriate, no matter how much the Go creator didn't like it. If even a single runtime error goes undetected/unhandled, you will end up further and further into an unknown state due to state corruption, and your behavior will soon become completely nondeterministic (or at least, nondeterministic-appearing). Losing determinism is the first step on the road to dragons.
I literally can't see how this wouldn't happen, and what I AM seeing is a lot of chatter in Go communities about how to manage this problem, when the solution is already there: Just fucking throw a stack trace. Or, even better, do what Erlang/Elixir do: Throw it, log it, and have a supervisor process kill it and restart it, all in 1 millisecond or less. If the error keeps happening above a certain threshold rate, kill and restart the supervisor as well. The reason this works (and has resulted in the INSANE uptimes that Erlang-backed services have) is that it resets state to programmer-known conditions.
On top of that, unwinding isn't the only way to get something where errors have to be handled or the program dies. Look at Swift's error handling for example: it's basically sugar over returned errors with correctness checks. Dead simple implementation, and dead simple to explain to users.
What I don't buy about the justifications for Go's design is that they were driven by the pure guiding hand of simplicity. It looks more to me like the designers simply treated language features they had seen done badly before as anathema and didn't try to think about how the mistakes could be corrected.
No, you don't panic, you are most likely to corrupt your data and maybe continue working as if everything was fine. If you are lucky, your code panics.
> ... you already know where to start debugging.
Grep all occurrences of "_"?
> That's much better than having an exception bubble up from deeeeep inside your code with some context-less cryptic message or number, isn't it?
No, the exception carries all the context you need. If you ignored a previous exception, the next one won't be as useful as it could, but at least your code breaks loudly.
There's no way to know whether the programmer actually considered all the error cases (they are generally very poorly documented in Go code), and there's no way to know if the called function added errors at some later date. If it's though an interface, there's no way to know that all implementations have the same errors.
It's really an 80s-era approach to error handling, and that's bad.
I don't see how that follows. A stack trace (as initially cryptic as it seems) is a record of all the code that would have affected the current buggy state you find yourself in. If anything, a stack trace isn't comprehensive enough, ideally it would include all known/named values at every level of the stack... a large quantity of information, to be sure, but perhaps it could be narrowed down by diffing each stack level with the previous one or something. But if you could have those 2 things, you would have literally ALL the information you needed to fix the bug. Since bugs are programmer-unexpected states, and the stack trace plus the known values at each stack level are LITERALLY the entire state.
So correct me if I'm wrong, if you don't assign an error to a variable on the same line in Go, it throws? Because it was my understanding that there were absolutely no throws at all in Go. Or is it only that certain kinds of statements are expected to possibly error, and must therefore be assigned to a variable (or _)?
Assigning to _ effectively ignores the error, but is considered a very bad practice.
Unavoidable runtime errors (eg divide by 0) will generate a panic, which is similar to an exception, but is uncatchable within the Go routine it originates in.
Nonsense.
fmt.Println("Hello world!")
I just ignored an error and it compiles fine. Go check the return type of Println:https://golang.org/pkg/fmt/#Println
tl;dr, it's very easy to accidentally ignore errors in functions that are side-effecting or modify parameters. Been there, done that.
"Syntax error, expected token HTTP_METHOD but got 'B'"
In Go, with proper error handling I'd get a message like:
"Couldn't do flubber transfer: Unable to negotiate protocol: Sent supported protocols but remote responded with HTTP 400 "Bad Request": Missing required field 'version' in protocol definition"
As "error" is an interface, this message is only the tip of the iceberg: the error object itself may contain the address of the remote server, the protocol definitions that were sent, the response body that we got and any other relevant contextual payload.
This is all due to the error being treated in-context as opposed to just bubbling up.
Well yeah, if you handle errors properly, you get better results than if you don't.
The point is that with exceptions, it fails loudly and you get the cryptic message even if you forget, whereas with Go, if you forget to handle an error, you just get weird behaviour and corrupt data.
And if you want more helpful error messages, you can catch the exceptions and report the context just as easily as you can in Go.
> I don't see how that follows. A stack trace (as initially cryptic as it seems) is a record of all the code that would have affected the current buggy state you find yourself in.
You get stack traces in Java, C#, Python, etc. You don't get them in C++ (well, you aren't guaranteed to get them).
(gdb) bt full I'm joining the Go team at Google
Sorry to hear that
Go is not revolutionary...> Not really.
I can assure you that it is indeed funny.