Slide 1

Slide 1 text

Rethinking Errors in Go Marcel van Lohuizen Go core team

Slide 2

Slide 2 text

r, err := os.Open(“foo.txt”) if err != nil { return fmt.Errorf(“oops: %v”, err) } defer r.Close()

Slide 3

Slide 3 text

Semantics first! Why? 
 error handling can be tricky

Slide 4

Slide 4 text

func writeToGS(c net.Context, bkt, dst string, r io.Reader) (err error) { 
 w := client.Bucket(bkt).Object(dst).NewWriter(c) defer w.CloseWithError(err) if _, err = io.Copy(w, r); err != nil { return fmt.Errorf(“oops: %v”, err)
 } return nil }

Slide 5

Slide 5 text

func writeToGS(c net.Context, bkt, dst string, r io.Reader) (err error) { err = errPanicking w := client.Bucket(bkt).Object(dst).NewWriter(c) defer w.CloseWithError(err) if _, err = io.Copy(w, r); err != nil { return fmt.Errorf(“oops: %v”, err)
 } return err } var errPanicking = errors.New(“panicking”) handle panic FAIL

Slide 6

Slide 6 text

func writeToGS(c net.Context, bkt, dst string, r io.Reader) (err error) { 
 w := client.Bucket(bkt).Object(dst).NewWriter(c) err = errPanicking defer func() { if err != nil { _ = w.CloseWithError(err) } else if err = w.Close(); err != nil { err = fmt.Errorf(“oh noes: %v”, err)
 } } if _, err = io.Copy(w, r); err != nil { return fmt.Errorf(“oops: %v”, err)
 } return err } return error from Close FAIL

Slide 7

Slide 7 text

func writeToGS(c net.Context, bkt, dst string, r io.Reader) (err error) { w := client.Bucket(bkt).Object(dst).NewWriter(c) err = errPanicking defer func() { if err != nil { _ = w.CloseWithError(err) } else if err = w.Close(); err != nil { err = fmt.Errorf(“oh noes: %v”, err) } }() if _, err = io.Copy(w, r); err != nil { return fmt.Errorf(“oops: %v”, err) } return nil } var errPanicking = errors.New(“panicking”)

Slide 8

Slide 8 text

how to approach simplifying this? semantics first!

Slide 9

Slide 9 text

Close

Slide 10

Slide 10 text

error

Slide 11

Slide 11 text

panic error

Slide 12

Slide 12 text

an error is recoverable panic is not 
 (sort of)

Slide 13

Slide 13 text

there is overlap not recognized in Go

Slide 14

Slide 14 text

Burner package
 (github.com/mpvl/errc)

Slide 15

Slide 15 text

funnel all errors, including panics, to a single error variable

Slide 16

Slide 16 text

func writeToGS(c net.Context, bkt, dst string, r io.Reader) (err error) { e := errc.Catch(&err) defer e.Handle()
 w := client.Bucket(bkt).Object(dst).NewWriter(c) e.Defer(w.CloseWithError, msg(“oh noes”)) _, err = io.Copy(w, r) e.Must(err, msg(“oh no”)) return nil }

Slide 17

Slide 17 text

semantics first pays off!

Slide 18

Slide 18 text

Try it out! Feedback Welcome! Marcel van Lohuizen, Go core Team github.com/mpvl/errc github.com/mpvl/errd @mpvl_