Neat. What you and I are doing is very similar. Particularly how the handler is "bound" to the error and checks to make sure that the error is non-nil before attempting to recover.
The differences I see in our approaches are as follows: I support wrapping an error or performing some arbitrary action. This wouldn't be difficult for you to add - just add a func() parameter to RecoverOn that is invoked when *err != nil. If you did that then we would both support performing actions whether an early return was triggered by check/ro.ReturnOn or a regular return with err set (assuming named return values). I bind the check function (what you call ro.ReturnOn) to the error so that it can set that when passed a non-nil error. This allows check to be used directly, for example, on a function that only returns an error: check(functionThatReturnsAnError()) Instead of having to do: err = functionThatReturnsAnError() ro.ReturnOn(err) Binding the check and done functions means returning them both from a call to handle.Error. This adds one more line of code (defer done()) but means that check doesn't exist without this step and given that Go complains about unused variables it takes some work to forget to do something with done. My hope is that this significantly reduces the risk of an unhandled panic. (It's still possible to just call done and forget to defer it or name done _ so that the compiler won't complain, etc., etc.) As an added bonus people can call this pair of functions whatever they want (check/done, try/handle, ReturnOn/RecoverOn...). When I first posted I thought it would be neat to do: check, handle := handle.Error // ... so that the shadowing would make it impossible to call handle.Error again. But then I added Chain. (It would be nice to get the handle.Errorf case down to one line but I haven't figured out a way to do that. Maybe something with how arguments to deferred function are evaluated but the function call itself isn't...) In check I wrap the error in an unexported type: type failure struct { error } If this manages to slip by the idea is that it should be reported as an "unhandled error" plus the text of the actual error. It is the responsibility of done to unwrap the error and perform any actions on that. I'm paranoid about invoking recover, only invoke it when the error is the unexported failure type and even then check to make sure that the recovered value matches the error value. It is possible to always recover and then if we recover something we weren't supposed to, re-panic, but then we lose all the context for the original panic. Looking back at the error handling problem outline I realized that I did not have the ability to add additional error handling actions. I added Chain a few days after my original post. Michael. On Saturday, February 20, 2021 at 4:21:10 PM UTC-5 michael...@gmail.com wrote: > FWIW, I've put together a tiny package that, with some tradeoffs, seems > useful for reducing boilerplate in the common case where a function simply > wants to return an error to its caller. > > https://github.com/Michael-F-Ellis/ro > > The code is almost trivial. It consists of two small functions, > ro.RecoverOn( err *error) and ro.ReturnOn(err error), used as follows: > > import "github.com/Michael-F-Ellis/ro" > > func myfunc() (err error) { > defer ro.RecoverOn(&err) > > err = SomeFunctionCall() > ro.ReturnOn(err) > > // Do more stuff > // ... > return > } > > ReturnOn panics if err is not nil. > > RecoverOn recovers from the panic raised by ReturnOn and the function > exits with whatever error value would have been returned > normally. RecoverOn does not interfere with panics arising outside > of ReturnOn. > > Benefits and tradeoffs (coding discipline, debugging, performance) are > discussed in the README. > > Feedback welcomed either in this thread or in the repo issues. > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/87c73aa0-2ea2-4125-8cc9-3fe7972a4db9n%40googlegroups.com.