| > We've seen it hundreds of times in all kinds of software. Functions that return bool instead of an error code. Where did the precise error vanish to? Poof, it's gone! A thousand times yes. Earlier this year, two of us spent a full day debugging a problem with some of our automation. Our team has pretty good automation, for the most part, but this particular problem was in kind of a dark corner. A shell script in the automation would start up a process in the background, and then send commands to that process. The background process could be slow to start up at times, so to deal with this, the commands running in the foreground had long timeouts if any. Guess what happens if the background process dies? Well, the shell script doesn't care, that's for sure, it wasn't watching for error codes in background processes. It was a bit of an adventure following the path from the foreground commands to the missing background process, and finding the log files for the background process. It's one of the things I like about writing this quick-and-dirty automation in Go--the error handling is so explicit that you'll usually end up with good logs explaining what went wrong and what the program was trying to do at the time. Much better than dealing with shell scripts. Shell scripts are quick to write but you're often left in a bad position when they fail in unexpected ways, or even in expected ways. (The actual bug we hunted down was traced to one missing line in a configuration file, but the problems with that piece of automation are far larger.) |
Never do
Always do: Needless to say, you should do this on EVERY printf statement.There. Isn't explicit erroring great ? NO IT ISN'T.
Needless to say, this has an almost direct translation to Go. Does anyone do this ? Of course not. In Go, like in C, like in shell scripting, in the vast majority of programs nearly all errors are ignored.
That's why exceptions are so very superior to explicit error handling : it accomplishes many things :
1) it alerts the user that an error occured. "Explicit error handling" like C, Go, most C++, ... do will simply silently attempt to proceed, likely turning a small error or a typo into a disaster or catastrophe. Silent database corruption, here we come !
2) It provides information about where the error occured. Stop me if this sounds familiar: "when an error is printed, and the program crashes, I download the source and grep it for what I think is a unique word in the error message. When it turns out it isn't I get cranky. When it turns out there isn't a unique word in the error I just sit down in a quiet corner and softly cry".
3) It allows for "layered" error management strategies. I'm not saying it gets it up to OCaml levels, but it is far superior to C or Go error management. In the main function, you catch any Exception for the various parts of the program you start, log it in a reasonable manner, alert if necessary, and restart the relevant portion of the program. Inside the parts of the program you catch finer grained exceptions with more explicit management.
4) it's far more concise.
So "explicit" error management ? Let's just be truthful here (just look at Github examples of C and Go code): it's really just ignoring errors.
You can find coding errors involving ignored errors in the Go standard library in minutes. Examples:
1) https://github.com/golang/go/blob/master/src/bufio/bufio.go#...
2) https://github.com/golang/go/blob/master/src/bufio/bufio.go#...
3) https://github.com/golang/go/blob/master/src/flag/flag.go#L5...
So even the Go core developers themselves can't be trusted to not ignore errors.