|
Quite apart from the Python discussion, the author captures why I prefer errors as values (a la Go) to exceptions (a la Java), and I have written both styles for many years. > Regardless of the specific approach, returning errors as values makes us consider all of the places an error could occur. The error scenarios become self-documenting and more thoroughly handled. This is so true. Most Java exception handling is a try/catch around about 20 lines of code, with superficial logging/rethrowing and no context about exactly what was being done to what when the exception occurred, just a filename/line# and a probably cryptic error message. In Go, best practice is something like: bytes, err := os.ReadFile("myfile.json")
if err != nil {
return nil, fmt.Errorf("reading file %s: %v", "myfile.json", err)
}
var data map[string]any
err = json.Unmarshal(bytes, &data)
if err != nil {
return fmt.Errorf("unpacking json from file %s: %v", "myfile.json", err)
}
This gives you precisely targeted errors that tell exactly what you were doing to what. Your future self will thank you when you're desperately trying to work out what went wrong last thing on a Friday.If you are going to replicate this with exceptions, it would require much more boilerplate, as his example demonstrates, which is ironic given that is the charge levelled at Go. |
In particular, the ReadFile example in Python will raise OSError, and those already include filename and error message. So you'd get the same result with 0 extra lines.
For the second example, the json unmarshalling will not auto-add filename, but its easy enough to do using exception chaining:
which will give stacktrace like: Note that's even more detailed than go, with significantly less boilerplate (only 3 lines per function) vs 3 lines per call.(an anecdote: we've had the team which converted the CLI tool from Python to Golang. The first time they ran the tool, it printed a single line:
and that's it. It took a lot of debugging before they could figure out what happened. All because they got used to python doing super-rich traceback automatically, with 0 effort from programmers)