Reputation: 6616
I've been reading this blog post but I'm still not convinced I know exactly what to do to get custom errors that I can return from my functions and handle outside of them.
This is what I'm currently doing:
func doSomething() int {
x := 0
// Do something with x.
...
if somethingBadHappened {
return -1
}
if somethingElseBadHappened {
return -2
}
return x
}
This is what I'd like to be doing:
func doSomething() int, ? {
...
if somethingBadHappened {
return ?, err
}
if somethingElseBadHappened {
return ?, err2
}
return x, nil
}
But I'm not exactly sure how, and what to replace those question marks with.
Upvotes: 4
Views: 2712
Reputation: 91399
I would turn
func doSomething() int, ? {
...
if somethingBadHappened {
return ?, err
}
if somethingElseBadHappened {
return ?, err2
}
return x, nil
}
into
func doSomething() (r int, err error) {
...
if somethingBadHappened {
err = err1 // Whatever satisfies the `error` interface
return
}
if somethingElseBadHappened {
err = err2 // dtto
return
}
return x, nil
}
IOW, at the call site it is idiomatic* to ignore, never use or rely on, any other returned value if err != nil, so just don't care if r
above has had been assigned some intermediate value or not.
(*) In the first approximatiom, i.e. if not stated otherwise. E.g. an io.Reader
explicitly declares it can return both err == io.EOF
and valid data at the same time:
When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-nil) error from the same call or return the error (and n == 0) from a subsequent call. An instance of this general case is that a Reader returning a non-zero number of bytes at the end of the input stream may return either err == EOF or err == nil. The next Read should return 0, EOF regardless.
Upvotes: 4
Reputation: 151
You don't really need to return an int if you don't want to. You can do something like:
func doSomething() error {
...
if somethingBadHappened {
return errors.New("something bad happened")
}
if somethingElseBadHappened {
return errors.New("something else bad happened")
}
return nil
}
or if you want to return ints
func doSomething() (int, error) {
...
if somethingBadHappened {
return -1, errors.New("something bad happened")
}
if somethingElseBadHappened {
return -2, errors.New("something else bad happened")
}
return x, nil
}
be sure to import "errors"
at the top.
If you want to test whether you got an error, you can do
x, err := doSomething()
if err != nil {
log.Println(err)
}
Upvotes: 8