For what it's worth, this is also a very common pattern in ruby, using blocks:
def with_error_handler
if error = yield
puts "error: #{error}"
end
end
def do_things
error = do_this
return "error doing this: #{error}" if error
error = do_that
return "error doing that: #{error}" if error
nil
end
with_error_handler do
do_things
end
Having said that, I did need to read the Go version more than once to grok it. I theoretically like Go's syntax for defining functions that take functions, but in practice I find it quite hard to scan, especially if there are more parameters on top of the function, or the passed function has multiple returns, or (god forbid!) it takes a function itself - it can all become quite a lot of bookkeeping.
yes, of course, but the discussion I replied to was talking about this specific idiom, this application of higher order functions, and not about the use of higher order functions generally.
It's important to compare with the previous slide, to see the problem this is trying to solve. It'd be really easy to do a lot of
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
all over the place, as the error return type isn't part of the standard Handler signature.
The decorator approach lets you return errors from your handlers, and then have your actual error handling centralized; you may want to send an e-mail to the ops team, send it to a third party exception management web service, etc.