SEANK.H.LIAO

go error handling musings

random thoughts on go error handling

errors

premise: Errors are values. Unless some fundamental constraint has been violated, in which case feel free to panic, errors are just some other state to be handled.

pain points: as far as I can tell, there are 2 main complaints:

verbose

For the first issue, people usually propose some syntax sugar to shorten if err != nil { ... }

How about a slightly more generic solution that checks against the zero value, then we can coopt the short circuiting behaviour of && to make the common case one line. A new unary operator !! evaluates to true if the operand is the zero value of its type, else false.

 1_, err = f() // currently valid
 2err != nil && return _, _, fmt.Errorf("foo: %w", err)
 3
 4_, err = g() // proposed, pre
 5!!err && return _, _, fmt.Errorf("bar: %w", err)
 6
 7_, err = h() // proposed, post
 8err!! && return _, _, fmt.Errorf("fizz: %w", err)
 9
10// equivalent function
11func z(v interface{}) bool {
12       return reflect.ValueOf(v).IsZero() // but that reflect penalty...
13}
14
15_, err = i()
16z(err) && return _, _, fmt.Errorf("buzz: %w", err)

Also really want _ to mean the zero value for any type...

I also thought the idea of assigning to an error handler was a good start, though it does have some issues, like implicit passing of arguments, handler having to be defined in function scope, and non local returns, I guess with some extra thought this is where the check/handle came from.

 1
 2func f() (err error) {
 3        handler := func(other arg, err error) {
 4                if err != nil {
 5                        err = fmt.Errorf("some extra context: %w", err)
 6                        return // non local return???
 7                }
 8        }
 9
10        var o arg
11
12        _, handler(o) = g()
13}
14
15func handler(err error, arg string) {
16        if err != nil {
17                return
18        }
19}
20

ignorable

Usually the people focusing in the second camp want sum types, forcing you to handle errors. People usually deal with this now with linters, and to be honest, I don't really think this is as much of a concern