Lovin' your errors
How a little TLC pays back with interest.
Roger Peppe
Canonical Ltd
Roger Peppe
Canonical Ltd
if err != nil {
return err
}func doSomething() {
foo()
bar()
baz()
}func doSomething() error {
if err := foo(); err != nil {
return err
}
if err := bar(); err != nil {
return err
}
if err := baz(); err != nil {
return err
}
return nil
}func doSomething() {
foo()
bar()
baz()
}// MustCompile is like Compile but panics if the expression cannot be parsed.
// It simplifies safe initialization of global variables holding compiled regular
// expressions.
func MustCompile(str string) *Regexp {
regexp, error := Compile(str)
if error != nil {
panic(`regexp: Compile(` + quote(str) + `): ` + error.Error())
}
return regexp
}if err != nil {
return err
}go get github.com/kisielk/errcheck % errcheck ./... agent/agent.go:654:11 buf.Write(data) agent/bootstrap.go:96:12 st.Close() agent/identity.go:29:12 os.Remove(c.SystemIdentityPath()) agent/tools/toolsdir.go:57:16 defer zr.Close()
// IncCounterAsync increases by one the counter associated with the composed
// key. The action is done in the background using a separate goroutine.
func (s *Store) IncCounterAsync(key []string) {
s.Go(func(s *Store) {
if err := s.IncCounter(key); err != nil {
logger.Errorf("cannot increase stats counter for key %v: %v", key, err)
}
})
}// Errors holds any errors encountered during the parallel run.
type Errors []error
func (errs Errors) Error() string {
switch len(errs) {
case 0:
return "no error"
case 1:
return errs[0].Error()
}
return fmt.Sprintf("%s (and %d more)", errs[0].Error(), len(errs)-1)
}var ErrNotFound = errors.New("not found")
err := environments.Find(bson.D{{"_id", id}}).One(&env)
if err == mgo.ErrNotFound {
return nil
}type PathError struct {
Op string
Path string
Err error
}
func (e *PathError) Error() string {
return e.Op + " " + e.Path + ": " + e.Err.Error()
}
err := os.Create("/tmp/something")
if err, ok := err.(*os.PathError); ok {
}type Error interface {
error
Timeout() bool // Is the error a timeout?
Temporary() bool // Is the error temporary?
}
if err, ok := err.(net.Error); ok && err.Temporary() {
...
}func IsNotExist(err error) bool {
switch pe := err.(type) {
case nil:
return false
case *PathError:
err = pe.Err
case *LinkError:
err = pe.Err
}
return err == syscall.ENOENT || err == ErrNotExist
}if err != nil {
return "", fmt.Errorf("cannot read random secret: %v", err)
}for {
select {
case msg := <-msgChan:
err := doSomething(msg.params)
msg.reply <- fmt.Errorf("cannot do something: %v", err)
...
}
}"cannot read random secret: unexpected EOF"
cannot get login entity: cannot get user "admin": mongo query failed: cannot acquire socket: cannot log in: error authorizing user "admin": request failed: cannot read reply: EOF
err := fmt.Errorf("cannot open file: %v", err)
if os.IsNotExist(err) {
// never reached
}if err != nil {
return errgo.Notef(err, "cannot read random secret")
}if errgo.Cause(err) == io.UnexpectedEOF {
...
}
if os.IsNotExist(errgo.Cause(err)) {
...
}return errgo.Mask(err)
// Preserve any cause return errgo.Mask(err, errgo.Any) // Preserve only some causes return errgo.Mask(err, os.IsNotExist, os.IsPermission)
return errgo.NoteMask(err, "cannot open database file", os.IsNotExist)
if err == mgo.IsNotFound {
return errgo.WithCausef(err, params.ErrNotFound, "no such document")
}fmt.Printf("%v\n", err)
cannot encrypt password: cannot read random secret: unexpected EOF
fmt.Printf("%#v", err)
[{/home/rog/src/github.com/juju/utils/encrypt.go:97: cannot encrypt password}
{/home/rog/src/github.com/juju/utils/password.go:32: cannot read random secret}
{unexpected EOF}]