$30 off During Our Annual Pro Sale. View Details »

Go 2 error values today

Go 2 error values today

Last year, the Go team introduced two draft designs related to errors in Go: one introducing new syntax and the other focussing on improved library support. With the help of community feedback, we have turned the latter into a proposal. An implementation, which is planned to be part of Go 1.13, is now in the Go source tree for evaluation. In this talk, I'll explain its design and how to use the new functionality today.

Marcel van Lohuizen

March 25, 2019

More Decks by Marcel van Lohuizen

Other Decks in Programming


  1. Go 2 Error Values Today dotGo 2019 Marcel van Lohuizen

    Google mpvl@golang.org Gopher by Renée French
  2. Previously at a theatre near you…

  3. End users Users of errors Developers Programs

  4. informative, succinct,
 possibly localized End users "ill-behaved gophers abound: hole

    in fence” "overal slecht gemanierde gophers: gat in hek”
  5. more detail Developers ill-behaved gophers abound:
 - hole

    in fence:
  6. Programs strings.Contains(err.Error(), "not exists") err == io.EOF p, ok :=

    err.(*PathError) error inspection
  7. Error values in core Today

  8. fmt.Errorf Common patterns in the core libraries if err !=

    nil { return fmt.Errorf("whoops: %v", err) }
  9. fmt.Errorf discards information fmt.Errorf

  10. Custom error type Common patterns in the core libraries return

    &PathError{"open", filename, err} In core p, ok := err.(*PathError) if p.Err == ... if os.IsPermission(err) { Is it an “exists” error? With helper
  11. Lack of standard for error wrapping leads to awkward code

    Custom error types
  12. github.com/pkg/errors Enter the community gopkg.in/errgo.v2/errors github.com/spacemonkeygo/errors go.uber.org/multierr upspin.io/errors github.com/juju/errors github.com/go-errors/errors

  13. Poor interoperability between the errors of these different packages fmt.Errorf

  14. Body Level One Body Level Two Body Level Three Body

    Level Four Title Text Where from here? Photo by Javier Allegue Barros on Unsplash
  15. Goal custom errors == good thing

  16. Goal need a standard and interoperability • inspection • details

    • localizability
  17. Body Level One Body Level Two Body Level Three Body

    Level Four Title Text Go 1.13 Photo by Proposal by Nick Youngson CC BY-SA 3.0 ImageCreator on Unsplash
  18. Inspection Proposal #29934

  19. Error inspection: Wrapper Programmatic analysis package errors type Wrapper interface

    { Unwrap() error } Optional interface func (e *PathError) Unwrap() error { return e.Err } Example implementation
  20. Error Inspection: errors.Is Programmatic analysis // Is reports whether err

    or any of the // errors in its chain is equal to target. func Is(err, target error) bool API for sentinel comparison // was if err == io.EOF { if errors.Is(err, io.EOF) { Example usage
  21. func Cause(err error) error This is not:

  22. Error inspection Programmatic analysis if errors.Is(err, os.ErrPermission) { … }

    Now if os.IsPermission(err) { … } Before
  23. Error inspection Programmatic analysis if errors.Is(err, net.ErrTimeout) { … }

    Now if err, ok := err.(net.Error); ok && err.Timeout() { … } Before
  24. Error Inspection: errors.As Programmatic analysis func As(err error, target interface{})

    bool API for type assertion // was if p, ok := err.(*os.PathError); ok { var p *os.PathError if errors.As(err, &p) { if p := (*os.PathError)(nil); errors.As(err, &p) { Example usage
  25. Printing Proposal #29934 Gopher by Renée French

  26. Normal versus Detail Common patterns in the core libraries ill-behaved

    gophers abound:
 - hole in fence:
 /home/gopher/src/den/fence/state.go:9 fmt.Printf("%+v", err) fmt.Printf("%v", err) ill-behaved gophers abound: hole in fence
  27. Error printing: Formatter and Printer Formatting package errors type Formatter

    interface { error FormatError(p Printer) (next error) } type Printer interface { Print(args ...interface{}) Printf(format string, args ...interface{}) Detail() bool } Interfaces
  28. Error details Formatting package errors func Caller(skip int) Frame type

    Frame struct { … } func (f Frame) Format(p *Printer) errors.Frame
  29. Error Printing: Example Formatting type PathError struct { Op, Path

    string Err error frame Frame } func (e *PathError) FormatError(p errors.Printer) error { p.Printf("%s %s", e.Op, e.Path) e.frame.Format(p) // Format calls p.Detail return e.Err } func (e *PathError) Error() string { return fmt.Sprint(e) }
  30. Body Level One Body Level Two Body Level Three Body

    Level Four Title Text Migration Photo by Jan-Niclas Aberle on Unsplash Adapting to the new standard
  31. • support Unwrap and make errors.Is work with: - os.ErrPermission

    - os.ErrExist - os.ErrNotExist - … • add location information through FormatError Core error types
  32. • print single stack frame in detailed mode Changes to

    errors.New and fmt.Errorf
  33. •FormatError to return err for 
 fmt.Errorf("oops: %v", err)

    %s", err) •also adds Unwrap for
 fmt.Errorf("oops: %w", err) Changes to fmt.Errorf
  34. Announcement new functionality available today: golang.org/x/xerrors

  35. import "golang.org/x/xerrors" type GopherError struct { frame xerrors.Frame err error

    } func (e *GopherError) Format(s fmt.State, verb rune) { xerrors.FormatError(e, s, verb) } func (e *GopherError) FormatError(p xerrors.Printer) error { p.Print("ill-behaving gophers abound") e.frame.Format(p) return err } func (e *GopherError) Error() string { return fmt.Sprint(e) } Using golang.org/x/xerrors
  36. Community

  37. @mpvl_ Thank you dotGo 2019 Marcel van Lohuizen Google mpvl@golang.org

    Gophers by Renée French