xm lian
xm lian

Reputation: 107

golang pkg/errors How to print custom wrapped errors?

My project wraps a custom error type errNotFound, which has an error embedded in it. Now I have a pkg/errors package that generates an error that prints the call stack. But when I inline this error into errNotFound, the call stack is not printed. Here is a sample, how can I change it?

simple:

package main

import (
    "fmt"

    stderrors "errors"
    "github.com/pkg/errors"
)

func findSomething() error {
    return errors.Errorf("something not found")
}

func main() {
    err := findSomething()
    // can print error stack
    exitf("Error1: %+v", err)

    fmt.Println()
    fmt.Println()
    // cannot print error stack
    err = ErrNotFound(err)
    exitf("Error2: %+v", err)
}

func exitf(format string, args ...interface{}) {
    fmt.Printf(format, args...)

    //os.Exit(1)
}

type errNotFound struct{ error }

func ErrNotFound(err error) error {
    if err == nil || IsErrNotFound(err) {
        return err
    }

    return errNotFound{err}
}

func IsErrNotFound(err error) bool {
    return stderrors.As(err, &errNotFound{})
}

output:

$ go run main
Error1: something not found
main.findSomething
        /home/lianxm/github.com/play_error/main.go:11
main.main
        /home/lianxm/github.com/play_error/main.go:15
runtime.main
        /usr/local/go/src/runtime/proc.go:255
runtime.goexit
        /usr/local/go/src/runtime/asm_amd64.s:1581

Error2: something not found

I know I can get the original error by err = errors.Unwrap(err) and then print it, but this means that I need to do this every time before printing, which is not very elegant code, and I don't really want to do that...

here is an example project: https://github.com/lianxmfor/play_error

Upvotes: 1

Views: 2418

Answers (3)

Manish Kushwaha
Manish Kushwaha

Reputation: 156

while calling exitf you can use errors.WithStack to print stack trace.

Upvotes: 0

serge-v
serge-v

Reputation: 780

you need to annotate the error with stack:

func ErrNotFound(err error) error {
        if err == nil || IsErrNotFound(err) {
                return err
        }

        return errors.WithStack(errNotFound{err})
}

Upvotes: 0

Is this necessary to put an error inside another if you already have your stack?

If yes... You can define a Method for errNotFound like:

func (e errNotFound) Error() string {
    return fmt.Printf("NotFound: %+v", e.err)
}

Upvotes: 1

Related Questions