note: updated 12023-04-17
if err != nil {
// handle error
}
Error handling seems to be a recurring theme in go, but most proposals get nowhere.
baseline code
x, err := foo()
if err != nil {
return nil, wrap(err)
}
note: almost all the ones that claim to use "plain functions" as error handlers have an implicit nonlocal return
handle err { return _, wrap(err) }
x := check foo()
handle err { return _, wrap(err) }
x, # := foo()
:handle func(err error) (T, error) { return _, wrap(err) }
x, ? := foo()
watch err { if err != nil { return _, wrap(err) } }
x, err != foo()
expect err != nil { return _, wrap(err) }
x, err := foo()
with { return _, wrap(err) }
handle err { x, err := foo() }
x, #err := foo()
catch err { return _, wrap(err) }
: tagged error handlersx, @err := foo()
err: return _, wrap(err)
: goto labelgrab err() { if err != nil { return _, wrap(err) } }
x, err() := foo()
: assign to handlererr := inline(err error){ if err != nil { return _, wrap(err) } }
x, err := foo()
: assign to handlererr := func(err error) (T, error) { return _, wrap(err) }
x, #err := foo()
: block scoped_check = func(err error) (T, error) { return _, wrap(err) }
x, ?err := foo()
: not fully formed idea on returnhandler := func(err error) (T, error) { return _, wrap(err) }
x, #handler(_) := foo()
: implicit nil checkhandler := func(err error) (T, error) { return^2 _, wrap(err) }
x, handler(err) := foo()
: note nonlocal returnhandler := func(err error) (T, error) { eject _, wrap(err) }
x, err := foo()
inject handler(err)
x, !err := foo() throw handler
catch handler { return wrap(err) }
goto x, err := foo()
r:
return _, wrap(err)
trap func(err2 error) { err = wrap(err2) }
x, _ := foo()
: like defer, triggers on every errorsome rely on wrap
being smart and passing through nil
(so not fmt.Errorf
),
x, err := foo()
reflow _, wrap(err)
: implicit err != nil
and returnx, err := foo()
refuse _, wrap(err)
x, err := foo()
pass wrap(err)
x, err := foo()
ereturn _, wrap(err)
x, err := foo()
err ?: return _, wrap(err)
x, err := foo()
on err, return _, wrap(err)
x, err := foo()
on err return handler()
x, err := foo()
err ? { return _, wrap(err) }
x, err := foo()
onErr { return _, wrap(err) }
x, err := foo()
try err: _, wrap(err)
x, err := foo()
try err, wrap
x, err := foo()
if err != nil { return _, wrap(err) }
, also: if ... on 1 linex, err := foo()
if err != nil { return wrap(err) }
: implicit zero values for other returnsx, err := foo()
if !err { return _, wrap(err) }
x, err := foo()
if err { return _, wrap(err) }
x, err := foo()
if err? { return _, wrap(err) }
x, err := foo()
if err != nil: return _, wrap(err)
x, err := foo()
return wrap(err) if err != nil
, alsox, err := foo()
return if err != nil { _, wrap(err) }
, alsox, err := foo()
return(err) wrap(err)
x, err := foo()
\ nil, wrap(err)
x, err := foo(); if err != nil { return _, wrap(err) }
, also: everything on 1 linex, err := foo() ?? { return _, wrap(err) }
x, err := foo() else { return _, wrap(err) }
x, err := foo() /* err */ { return _, wrap(err) }
,x, err := foo() { return _, wrap(err) }
, alsox, err := foo(); err.return wrap(err)
x, err := foo() err? wrap(err)
x, wrap() := foo()
x, wrap(err) := foo()
x, #wrap(_) := foo()
x := foo() or err: return _, wrap(err)
x := foo() ?err return _, wrap(err)
x := check wrap() foo()
, alsox := check foo() with wrap(err)
x := check foo(); err { return _, wrap(err) }
x := foo() ? wrap()
x := foo() or wrap
x := foo() || wrap(err)
x := foo() on_error err fail wrap(err)
x := foo() onerr return _, wrap(err)
x := foo() // error: err => wrap(err)
error handling in commentsx := try(foo(), wrap)
x := try foo() or return _err
x := try foo(), wrap
x := collect(&err, foo(), wrap)
if x, err := foo(); err != nil then return _, wrap(err)
try x, err := foo() { return _, wrap(err) }
x :=. foo()
x := try(foo())
x := must(foo())
: panic instead of returnx := handle foo()
x := guard foo()
x := must foo()
x := foo!()
x := foo()?
, also, alsox := #foo()
x, # := foo()
: panic instead of returnx, ~ := foo()
: wrap with stacktracesx, - := foo()
x, ? := foo()
, also, alsox, ! := foo()
, also, panicx, !! := foo()
x, !err := foo()
x, ^err := foo()
x, err? := foo()
x, err := foo() throws err
x, check err := foo()
x, err := foo()
: builtin implicit nil checkx, err := foo()
check(err)
: builtin if err != nil { return ..., err }
macrox, err := foo()
catch(err)
: builtin if err != nil { return ..., err }
macrox := foo().handleErr()
: builtin if err != nil { return ..., err }
macrox := foo() -> throw err
try { x := foo() } catch(e Exception) { ??? }
, also: literally try catchtry err != nil { x, err := foo() } except { return _, wrap(err) }
try { x := foo(); if err != nil { return _, wrap(err) } }
try { x, $ := foo() } catch(err) { return _, wrap(err) }
until err != nil { check x, err := foo() } else { return _, wrap(err) }
: insert after every check
break err != nil { step: x, err := foo() }
: insert after every repeatable labelbreak err != nil { try x, err := foo() }
: insert after every try
if x, err := foo(); err != nil { return _, wrap(err) } else { ... } undo { ??? } done { ??? } defer { ??? }
handler := func(err error) error { return wrap(err) }
check(handler){ x := foo() }
check { x := check foo() } handle err { return _, wrap(err) }
check { x, err1 := foo() } catch err { return _, wrap(err) }
check { x, err := foo()
catch: return _, wrap(err) }
x, err := foo() !!!
fail: return _, wrap(err)
: goto labelhandle err { x, err := foo()
case err != nil: return _, wrap(err) }
throw "err"
catch func(err error) { return _, wrap(err) }
x, (err) := foo()
: only assign to LHS if ()
content is not currently nil
collect err { x, _! := foo() }
if err != nil { return _, wrap(err) }
: err is an value that accumulates errors? does it continue?errorhandling(err){ x, err := foo() }
: err is an accumulator? messes with typesx, err := foo()
handle err1 || err2 || err3 { return _, wrap(err) }
: shorter if chain?returnfrom label, err
: nonlocal returnvalue|err
allows passthroughif x, err := foo().bar().baz(); err != nil { return _, wrap(err) }
: chaining method calls with return type (T, error)
func foo() (return, string)
: return is a type of bool that does... somethingErrorOr[T]
: new convention instead of return T, err
x := foo()
if x@error != nil { ... }
template handler(err error, x expression) { if err != nil { inline(x); panic(err) } }
x, err := foo()
handler(err, { err = wrap(err) })
tryfunc func(...){ x := foo() }
: new function type, implicit error checks, implicit error return value