Trace Error
Error wrapping with file, line, and function name using runtime.Caller.
package main
import (
"errors"
"fmt"
"path/filepath"
"runtime"
)
type TraceError struct {
File string
Func string
Line int
Err error
}
func (e *TraceError) Error() string {
return fmt.Sprintf("%s:%d:%s %s", e.File, e.Line, e.Func, e.Err.Error())
}
func (e *TraceError) Unwrap() error {
return e.Err
}
func WrapError(err error) error {
if err == nil {
return nil
}
if _, ok := err.(*TraceError); ok {
return err // avoid double wrapping
}
pc, file, line, ok := runtime.Caller(1)
if !ok {
return &TraceError{Err: err}
}
return &TraceError{
File: filepath.Base(file),
Func: filepath.Base(runtime.FuncForPC(pc).Name()),
Line: line,
Err: err,
}
}
// Sentinel errors
var ErrNotFound = errors.New("not found")
var ErrDuplicate = errors.New("duplicate")
func findBookmark(id string) error {
return WrapError(fmt.Errorf("bookmark %s: %w", id, ErrNotFound))
}
func main() {
err := findBookmark("abc-123")
if err != nil {
fmt.Println(err)
// Check the underlying error
if errors.Is(err, ErrNotFound) {
fmt.Println("it's a not-found error")
}
}
}