Remove the errors.e type (#11)

* rename loc type to location

* move locationer interface inside Fprint, rename to location

* refactor Wrap/Wrapf into helper method

* remove errors.e type, compose an anon struct in wrap and add a Message() interface method to extract the cause message
This commit is contained in:
Dave Cheney 2016-04-26 12:25:34 +10:00
parent f85d45fecf
commit 3612ec480e

View File

@ -56,9 +56,11 @@ import (
"strings" "strings"
) )
type loc uintptr // location represents a program counter that
// implements the Location() method.
type location uintptr
func (l loc) Location() (string, int) { func (l location) Location() (string, int) {
pc := uintptr(l) - 1 pc := uintptr(l) - 1
fn := runtime.FuncForPC(pc) fn := runtime.FuncForPC(pc)
if fn == nil { if fn == nil {
@ -112,26 +114,21 @@ func New(text string) error {
pc, _, _, _ := runtime.Caller(1) pc, _, _, _ := runtime.Caller(1)
return struct { return struct {
error error
loc location
}{ }{
errors.New(text), errors.New(text),
loc(pc), location(pc),
} }
} }
type e struct { type cause struct {
cause error cause error
message string message string
loc
} }
func (e *e) Error() string { func (c cause) Error() string { return c.Message() + ": " + c.Cause().Error() }
return e.message + ": " + e.cause.Error() func (c cause) Cause() error { return c.cause }
} func (c cause) Message() string { return c.message }
func (e *e) Cause() error {
return e.cause
}
// Wrap returns an error annotating the cause with message. // Wrap returns an error annotating the cause with message.
// If cause is nil, Wrap returns nil. // If cause is nil, Wrap returns nil.
@ -140,11 +137,7 @@ func Wrap(cause error, message string) error {
return nil return nil
} }
pc, _, _, _ := runtime.Caller(1) pc, _, _, _ := runtime.Caller(1)
return &e{ return wrap(cause, message, pc)
cause: cause,
message: message,
loc: loc(pc),
}
} }
// Wrapf returns an error annotating the cause with the format specifier. // Wrapf returns an error annotating the cause with the format specifier.
@ -154,10 +147,19 @@ func Wrapf(cause error, format string, args ...interface{}) error {
return nil return nil
} }
pc, _, _, _ := runtime.Caller(1) pc, _, _, _ := runtime.Caller(1)
return &e{ return wrap(cause, fmt.Sprintf(format, args...), pc)
cause: cause, }
message: fmt.Sprintf(format, args...),
loc: loc(pc), func wrap(err error, msg string, pc uintptr) error {
return struct {
cause
location
}{
cause{
cause: err,
message: msg,
},
location(pc),
} }
} }
@ -187,10 +189,6 @@ func Cause(err error) error {
return err return err
} }
type locationer interface {
Location() (string, int)
}
// Print prints the error to Stderr. // Print prints the error to Stderr.
// If the error implements the Causer interface described in Cause // If the error implements the Causer interface described in Cause
// Print will recurse into the error's cause. // Print will recurse into the error's cause.
@ -209,15 +207,21 @@ func Print(err error) {
// The format of the output is the same as Print. // The format of the output is the same as Print.
// If err is nil, nothing is printed. // If err is nil, nothing is printed.
func Fprint(w io.Writer, err error) { func Fprint(w io.Writer, err error) {
type location interface {
Location() (string, int)
}
type message interface {
Message() string
}
for err != nil { for err != nil {
location, ok := err.(locationer) if err, ok := err.(location); ok {
if ok { file, line := err.Location()
file, line := location.Location()
fmt.Fprintf(w, "%s:%d: ", file, line) fmt.Fprintf(w, "%s:%d: ", file, line)
} }
switch err := err.(type) { switch err := err.(type) {
case *e: case message:
fmt.Fprintln(w, err.message) fmt.Fprintln(w, err.Message())
default: default:
fmt.Fprintln(w, err.Error()) fmt.Fprintln(w, err.Error())
} }