I primarily use this in three areas:
Command line tools: if any part of the command fails, you usually don't want to continue, unless it is a long-running batch process. In that case, I usually also write a logOnError() function to keep track of problematic work items.
Servers: during server initialization, there are many circumstances where it doesn't make sense to continue, such as template compilation failure or failing to open the socket.
Other: I use dieOnError anywhere it would otherwise make sense to use panic() - situations where continuing the program would mean running in an unknown state, like out-of-memory conditions.
I've built systems with complex error handling before, but my teams have always run into the problem of trying to reason about complex, unpredictable program state. If the requirements can allow for the program to fail fast (as you say, "punting the whole problem"), then the code itself can be kept much simpler and easier to reason about. When errors do crop up, it is easier to look at logs to debug a simple program (or infrastructure issue) than to debug a complex program where you aren't sure how earlier errors affected state.
In languages with exceptions, this is sort of the default - if you don't handle an exception, the program will crash. Often there will be a main level exception handler that logs otherwise uncaught errors. But a problem in Go is that programs are default-alive on errors. If you don't check the error status of every single function call that returns errors, then the program can get into unknown state. So in production code, especially code that just combines a few libraries, every function call ends up taking 3 or 4 lines (1 line of call and/or 3 lines of error checking).
Regarding the number of return values, my dieOnError/logOnError only handles functions that return error and nothing else. If the function returns multiple values, I first call it, then call dieOnError with the err:
foo, bar, err := baz()
dieOnErr(err)
//assume foo and bar are valid
I suspect I could write a variadic error checking function that assumes the last parameter is error:
func dieOnError(a ...interface{}) {
//do some reflection magic?
}
func foo() (bar int, baz int, err error) {
...
}
//maybe needs some type assertions or something?
bar, baz := dieOnError(foo())