Assuming that scary.MightNotWork() is some kind of ancillary function that is non-essential, why would I want to let it impact the main program. The example that comes to mind would be logging. If I have set up my own "Write logs into network share" call, I'd never ever expect it to throw errors that took down the app. Share down? Don't care. logfile locked/corrupt. Don't care. Try and log, if you can't, fail silently without impacting the main purpose of the application/service/whatever.
> Try and log, if you can't, fail silently without impacting the main purpose of the application/service/whatever.
Are you being serious? I agree that there can be "some kind of ancillary function that is non-essential" but in the case of failed logging you should try sending an email / showing some warning if you have a GUI / try other outputs / crash with a meaningful error especially if you are running under some sort of supervisor... etc.
Of course that doesn't invalidate your main point.
Sure. If your function does things internally that might return errors, the normal thing to do is have your function also potentially return an error, namely the first error it finds.
If you call a function the error of which isn't a big deal to your function, you'd normally check the return value to make sure it meets your expectations. If it does, fine -- proceed accordingly. If it doesn't, then send the error up the chain.
So -- totally bogus example -- say you want to return the mod time of a file or, if the file doesn't exist, the epoch. The file not existing is an error, but not one you'd abort on; other file errors though would be problematic:
// ModOrEpoch returns the modification time of the file at path, or the epoch
// time if there is no such file. Unexpected file conditions are returned
// as errors.
func ModOrEpoch(path string) (time.Time, error) {
epoch := time.Unix(0, 0)
info, err := os.Stat(path)
if err != nil {
if os.IsNotExist(err) {
return epoch, nil
}
return time.Now(),
fmt.Errorf("File error for %s: %s", path, err.Error())
}
if info.IsDir() {
return time.Now(),
fmt.Errorf("File is a directory: %s", path)
}
return info.ModTime(), nil
}
I suppose it's possible you might really, really not care about an error, but that would be extremely un-idiomatic in Go. And, I would argue, a very bad habit in any language where the error could possibly be other than what you expect; sort of like
The thing that bugs me about seeing the errors ignored in official docs is that the Go world puts a lot of emphasis on writing idiomatic code, and the Go "idiom" is much less flexible than, say, Perl's. You might reasonably look to the official documentation to learn what is and isn't idiomatic. And you would hopefully figure out soon enough that ignoring errors isn't, but then again you might not.
> I would argue, a very bad habit in any language where the error could possibly be other than what you expect
Assuming that ModOrEpoch was being used to populate a mouseover somewhere on a ui that literally could not be less important, any error propagation is going to be degrading service considerably more than swallowing any error and returning epoch time.
Unless there is (and there could well be) a subset of errors which actually cause serious concerns but don't cause errors in any other function in the application? Do you have any examples/thoughts of what that might entail. :)
I think I might not be getting my point across here.
I'm not saying you should propagate the error all the way up to the end-user in a UI.
I'm saying that you very, very rarely would be so uninterested in a lower-level error that you wouldn't even want to log it, except for a set of expected errors.
So when we imagine a "subset of errors which actually cause serious concerns," we should be realistic about what "serious" means -- but I say that for the "subset" that is all unexpected errors, the minimum level of "serious" is that you want to know it happened. In my contrived example code, imagine the web server process doesn't have permission to stat the given file. You'd want to knwo about that, right?
If you're not doing the mouseover properly N% of the time, you have a more-or-less serious problem with your UI, and you presumably want to know that's happening and why. Maybe what you do about it is expand your set of known errors. But at least you have the option of doing something about it.
Assuming that scary.MightNotWork() is some kind of ancillary function that is non-essential, why would I want to let it impact the main program. The example that comes to mind would be logging. If I have set up my own "Write logs into network share" call, I'd never ever expect it to throw errors that took down the app. Share down? Don't care. logfile locked/corrupt. Don't care. Try and log, if you can't, fail silently without impacting the main purpose of the application/service/whatever.