Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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
Tweet

More Decks by Marcel van Lohuizen

Other Decks in Programming

Transcript

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

    in fence” "overal slecht gemanierde gophers: gat in hek”
  2. fmt.Errorf Common patterns in the core libraries if err !=

    nil { return fmt.Errorf("whoops: %v", err) }
  3. 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
  4. Body Level One Body Level Two Body Level Three Body

    Level Four Title Text Where from here? Photo by Javier Allegue Barros on Unsplash
  5. 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
  6. Error inspection: Wrapper Programmatic analysis package errors type Wrapper interface

    { Unwrap() error } Optional interface func (e *PathError) Unwrap() error { return e.Err } Example implementation
  7. 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
  8. Error inspection Programmatic analysis if errors.Is(err, net.ErrTimeout) { … }

    Now if err, ok := err.(net.Error); ok && err.Timeout() { … } Before
  9. 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
  10. Normal versus Detail Common patterns in the core libraries ill-behaved

    gophers abound:
 main.main
 /home/gopher/src/den/main.go:10
 - hole in fence:
 fence.Check
 /home/gopher/src/den/fence/state.go:9 fmt.Printf("%+v", err) fmt.Printf("%v", err) ill-behaved gophers abound: hole in fence
  11. 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
  12. Error details Formatting package errors func Caller(skip int) Frame type

    Frame struct { … } func (f Frame) Format(p *Printer) errors.Frame
  13. 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) }
  14. 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
  15. • support Unwrap and make errors.Is work with: - os.ErrPermission

    - os.ErrExist - os.ErrNotExist - … • add location information through FormatError Core error types
  16. •FormatError to return err for 
 fmt.Errorf("oops: %v", err)
 fmt.Errorf("oops:

    %s", err) •also adds Unwrap for
 fmt.Errorf("oops: %w", err) Changes to fmt.Errorf
  17. 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