The reason is that errors.Errorf initializes new fundamental error type (in pkg/errors). If you will look at its method Format(s fmt.State, verb rune) (which is triggered when you do log.Printf):
func (f *fundamental) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
io.WriteString(s, f.msg)
f.stack.Format(s, verb)
return
}
fallthrough
case 's':
io.WriteString(s, f.msg)
case 'q':
fmt.Fprintf(s, "%q", f.msg)
}
}
So you see that it just prints io.WriteString(s, f.msg).
Also, Errorf is:
func Errorf(format string, args ...interface{}) error {
return &fundamental{
msg: fmt.Sprintf(format, args...),
stack: callers(),
}
}
Because of the line: fmt.Sprintf(format, args...) you see the error of go vet (you can't pass %w to Sprintf), and in the print of the error msg you just see:
Es gab einen Fehler: %!w(*errors.fundamental=&{failing unconditionally 0xc0000a2000})
Whereas when using Wrap method, you get withStack error type, which its Format method is:
func (w *withStack) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
fmt.Fprintf(s, "%+v", w.Cause())
w.stack.Format(s, verb)
return
}
fallthrough
case 's':
io.WriteString(s, w.Error())
case 'q':
fmt.Fprintf(s, "%q", w.Error())
}
}
Thanks to this line fmt.Fprintf(s, "%+v", w.Cause()), you see a nice recursive stack trace.
Basically, you need to use %w like this:
fmt.Errorf("got error: %w", err)
But this won't help in case you want to print the stack.
What you can do maybe is to implement yourself a function for recursively printing the stack trace, which will work on an error chain of either fmt or pkg/errors:
type stackTracer interface {
StackTrace() errors.StackTrace
}
type unwrapper interface {
Unwrap() error
}
func printStack(err error) {
if err == nil {
return
}
if ster, ok := err.(stackTracer); ok {
fmt.Printf("%+v", ster)
}
if wrapped, ok := err.(unwrapper); ok {
printStack(wrapped.Unwrap())
}
}
https://play.golang.org/p/OsEPD6guWtO