Consider the following code (https://go.dev/play/p/hDOyP3W_lqW)
package main
import (
"log"
"github.com/pkg/errors"
)
func myError() error {
return errors.New("failing unconditionally")
}
func myError1() error {
return errors.Errorf("annotate with additional debug info: % v", myError())
}
func myError2() error {
return errors.Errorf("extra debug info: % v", myError1())
}
func main() {
if err := myError2(); err != nil {
log.Printf("% v", err)
}
}
I originate the error with errors.New
and annotate it with additional info using errors.Errorf
.
It does what I want--record and print the stack trace & line number. However, the problem is that the output of log.Printf("% v", err)
is verbose and repetitive:
2009/11/10 23:00:00 extra debug info: annotate with additional debug info: failing unconditionally
main.myError
/tmp/sandbox3329712514/prog.go:10
main.myError1
/tmp/sandbox3329712514/prog.go:14
main.myError2
/tmp/sandbox3329712514/prog.go:18
main.main
/tmp/sandbox3329712514/prog.go:22
runtime.main
/usr/local/go-faketime/src/runtime/proc.go:250
runtime.goexit
/usr/local/go-faketime/src/runtime/asm_amd64.s:1571
main.myError1
/tmp/sandbox3329712514/prog.go:14
main.myError2
/tmp/sandbox3329712514/prog.go:18
main.main
/tmp/sandbox3329712514/prog.go:22
runtime.main
/usr/local/go-faketime/src/runtime/proc.go:250
runtime.goexit
/usr/local/go-faketime/src/runtime/asm_amd64.s:1571
main.myError2
/tmp/sandbox3329712514/prog.go:18
main.main
/tmp/sandbox3329712514/prog.go:22
runtime.main
/usr/local/go-faketime/src/runtime/proc.go:250
runtime.goexit
/usr/local/go-faketime/src/runtime/asm_amd64.s:1571
iiuc, errors
package appends an additional copy of stack trace to the error every time of annotating the error, as can be seen in the below snippet
// repetitive (thrice) error stack
main.myError
/tmp/sandbox3329712514/prog.go:10
main.myError1
/tmp/sandbox3329712514/prog.go:14
main.myError2
/tmp/sandbox3329712514/prog.go:18
main.main
/tmp/sandbox3329712514/prog.go:22
runtime.main
/usr/local/go-faketime/src/runtime/proc.go:250
runtime.goexit
/usr/local/go-faketime/src/runtime/asm_amd64.s:1571
main.myError1
/tmp/sandbox3329712514/prog.go:14
main.myError2
/tmp/sandbox3329712514/prog.go:18
main.main
/tmp/sandbox3329712514/prog.go:22
runtime.main
/usr/local/go-faketime/src/runtime/proc.go:250
runtime.goexit
/usr/local/go-faketime/src/runtime/asm_amd64.s:1571
main.myError2
/tmp/sandbox3329712514/prog.go:18
main.main
/tmp/sandbox3329712514/prog.go:22
runtime.main
/usr/local/go-faketime/src/runtime/proc.go:250
runtime.goexit
/usr/local/go-faketime/src/runtime/asm_amd64.s:1571
My desired output is
// Desired output
2009/11/10 23:00:00 extra debug info: annotate with additional debug info: failing unconditionally
main.myError
/tmp/sandbox3329712514/prog.go:10
main.myError1
/tmp/sandbox3329712514/prog.go:14
main.myError2
/tmp/sandbox3329712514/prog.go:18
main.main
/tmp/sandbox3329712514/prog.go:22
runtime.main
/usr/local/go-faketime/src/runtime/proc.go:250
runtime.goexit
/usr/local/go-faketime/src/runtime/asm_amd64.s:1571
One way to achieve that is to only use the errors
package to originate the error and then use fmt.Errorf
with % v
to add additional info in the call stack (like this https://go.dev/play/p/OrWe6KUIL_m). However, it's error-prone and hard to enforce every developer to use this pattern in a large code base. Developers have to remember to use the errors
package to originate the error and use fmt
properly with % v
%s
to print out the stack trace.
I'm wondering if this is the desired behavior (verbose and repetitive). And is it possible to consistently use the errors
package to annotate errors along the call stack without worrying about appending repetitive stack trace copies (e.g., the errors
magically knows the error already has a stack trace)?
CodePudding user response:
there are v
format specifiers for printing an error.
%s - print the error. If the error has a Cause it will be printed recursively.
%v – It will print only values. The field name will not be printed. This is the default way of printing a struct when using Println (print the error