I work regularly in Go - for an isolated example, that's about as clean as it gets. If you want to make it a little more middleware-y you could do this:
func iferr(err *error, f func()) {
if err != nil { f() }
}
// use
func whatever(...) (err error) {
thing := ...
defer iferr(&err, thing.Method)
}
But that only works with an exact match, so that example can't match e.g. `Close() error`, so you still have to either make a ton of near-clones for different signatures, or use a ton of trivial closures (like with the manual version), to make the type system happy.Which can be worth it in a large enough project - `func()` and `func() error` will take care of like 90% of the signatures you'd defer anyway. I'd probably do that personally, unless I only needed it once or twice.
There has been a somewhat similar check/handle proposal (close to "try"), but it has consistently fallen into "they're great for trivial cases, but they make it harder to have good error messages / wrap errors with additional context", which is absolutely necessary in Go since errors are so loosely typed and contain only explicitly-added information (no stacks by default, for example). So I'm glad they haven't happened yet.
Ah, and: yes! You're right, it does fail to return any `result`. That was unintended, and as-written it won't complain, since `thing` is "used" (methods are called on it) and `result` does not need to be used: https://play.golang.org/p/iSU5YWyxODC
(Also I'm not sure if the compiler would catch this, but there seems to be a bug in that Go code that's hard to see at a glance. You're never assigning a value to result)