Destructure New/Errorf
Destructure New/Errorf into two components, a call to the stdlib
errors.New or fmt.Errorf to generate a _fundamental_ error, and then a
call to withStack to attach a stack trace to the message.
diff --git a/errors.go b/errors.go
index 71f1431..d3d2234 100644
--- a/errors.go
+++ b/errors.go
@@ -87,37 +87,16 @@
package errors
import (
+ "errors"
"fmt"
"io"
)
-// _error is an error implementation returned by New and Errorf
-// that implements its own fmt.Formatter.
-type _error struct {
- msg string
- *stack
-}
-
-func (e _error) Error() string { return e.msg }
-
-func (e _error) Format(s fmt.State, verb rune) {
- switch verb {
- case 'v':
- if s.Flag('+') {
- io.WriteString(s, e.msg)
- fmt.Fprintf(s, "%+v", e.StackTrace())
- return
- }
- fallthrough
- case 's':
- io.WriteString(s, e.msg)
- }
-}
-
// New returns an error with the supplied message.
func New(message string) error {
- return _error{
- message,
+ err := errors.New(message)
+ return &withStack{
+ err,
callers(),
}
}
@@ -125,12 +104,32 @@
// Errorf formats according to a format specifier and returns the string
// as a value that satisfies error.
func Errorf(format string, args ...interface{}) error {
- return _error{
- fmt.Sprintf(format, args...),
+ err := fmt.Errorf(format, args...)
+ return &withStack{
+ err,
callers(),
}
}
+type withStack struct {
+ error
+ *stack
+}
+
+func (w *withStack) Format(s fmt.State, verb rune) {
+ switch verb {
+ case 'v':
+ if s.Flag('+') {
+ io.WriteString(s, w.Error())
+ w.stack.Format(s, verb)
+ return
+ }
+ fallthrough
+ case 's':
+ io.WriteString(s, w.Error())
+ }
+}
+
type cause struct {
cause error
msg string
diff --git a/stack.go b/stack.go
index 243a64a..6b1f289 100644
--- a/stack.go
+++ b/stack.go
@@ -100,6 +100,19 @@
// stack represents a stack of program counters.
type stack []uintptr
+func (s *stack) Format(st fmt.State, verb rune) {
+ switch verb {
+ case 'v':
+ switch {
+ case st.Flag('+'):
+ for _, pc := range *s {
+ f := Frame(pc)
+ fmt.Fprintf(st, "\n%+v", f)
+ }
+ }
+ }
+}
+
func (s *stack) StackTrace() StackTrace {
f := make([]Frame, len(*s))
for i := 0; i < len(f); i++ {