> 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.