Skip to content

Commit 725b1a2

Browse files
committed
Implement errors.As
1 parent 940bed6 commit 725b1a2

File tree

4 files changed

+74
-0
lines changed

4 files changed

+74
-0
lines changed

error.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,3 +202,8 @@ func (err *Error) TypeName() string {
202202
}
203203
return reflect.TypeOf(err.Err).String()
204204
}
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_backward.go

Lines changed: 35 additions & 0 deletions
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.

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)