Skip to content

Commit 5c4c70f

Browse files
authored
Merge pull request #31 from waschik/master
Add "As" of standard errors module
2 parents 7c02372 + 725b1a2 commit 5c4c70f

File tree

5 files changed

+77
-4
lines changed

5 files changed

+77
-4
lines changed

error.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,6 @@ func WrapPrefix(e interface{}, prefix string, skip int) *Error {
139139

140140
}
141141

142-
143142
// Errorf creates a new error with the given message. You can use it
144143
// as a drop-in replacement for fmt.Errorf() to provide descriptive
145144
// errors in return values.
@@ -203,3 +202,8 @@ func (err *Error) TypeName() string {
203202
}
204203
return reflect.TypeOf(err.Err).String()
205204
}
205+
206+
// Return the wrapped error (implements api for As function).
207+
func (err *Error) Unwrap() error {
208+
return err.Err
209+
}

error_1_13.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ import (
66
baseErrors "errors"
77
)
88

9+
// find error in any wrapped error
10+
func As(err error, target interface{}) bool {
11+
return baseErrors.As(err, target)
12+
}
13+
914
// Is detects whether the error is equal to a given error. Errors
1015
// are considered equal by this function if they are matched by errors.Is
1116
// or if their contained errors are matched through errors.Is

error_1_13_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,10 @@ type errorWithCustomIs struct {
5959
}
6060

6161
func (ewci errorWithCustomIs) Error() string {
62-
return "["+ewci.Key+"]: " + ewci.Err.Error()
62+
return "[" + ewci.Key + "]: " + ewci.Err.Error()
6363
}
6464

6565
func (ewci errorWithCustomIs) Is(target error) bool {
6666
matched, ok := target.(errorWithCustomIs)
6767
return ok && matched.Key == ewci.Key
68-
}
68+
}

error_backward.go

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,41 @@
22

33
package errors
44

5+
import (
6+
"reflect"
7+
)
8+
9+
type unwrapper interface {
10+
Unwrap() error
11+
}
12+
13+
// As assigns error or any wrapped error to the value target points
14+
// to. If there is no value of the target type of target As returns
15+
// false.
16+
func As(err error, target interface{}) bool {
17+
targetType := reflect.TypeOf(target)
18+
19+
for {
20+
errType := reflect.TypeOf(err)
21+
22+
if errType == nil {
23+
return false
24+
}
25+
26+
if reflect.PtrTo(errType) == targetType {
27+
reflect.ValueOf(target).Elem().Set(reflect.ValueOf(err))
28+
return true
29+
}
30+
31+
wrapped, ok := err.(unwrapper)
32+
if ok {
33+
err = wrapped.Unwrap()
34+
} else {
35+
return false
36+
}
37+
}
38+
}
39+
540
// Is detects whether the error is equal to a given error. Errors
641
// are considered equal by this function if they are the same object,
742
// or if they both contain the same error inside an errors.Error.
@@ -19,4 +54,4 @@ func Is(e error, original error) bool {
1954
}
2055

2156
return false
22-
}
57+
}

error_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,29 @@ func BenchmarkStackFormat(b *testing.B) {
3030
}
3131
}
3232

33+
func TestAs(t *testing.T) {
34+
var errStrIn errorString = "TestForFun"
35+
36+
var errStrOut errorString
37+
if As(errStrIn, &errStrOut) {
38+
if errStrOut != "TestForFun" {
39+
t.Errorf("direct errStr value is not returned")
40+
}
41+
} else {
42+
t.Errorf("direct errStr is not returned")
43+
}
44+
45+
errStrOut = ""
46+
err := Wrap(errStrIn, 0)
47+
if As(err, &errStrOut) {
48+
if errStrOut != "TestForFun" {
49+
t.Errorf("wrapped errStr value is not returned")
50+
}
51+
} else {
52+
t.Errorf("wrapped errStr is not returned")
53+
}
54+
}
55+
3356
func TestStackFormat(t *testing.T) {
3457

3558
defer func() {
@@ -316,3 +339,9 @@ func callersToFrames(callers []uintptr) []runtime.Frame {
316339
}
317340
}
318341
}
342+
343+
type errorString string
344+
345+
func (e errorString) Error() string {
346+
return string(e)
347+
}

0 commit comments

Comments
 (0)