...
1
2
3
4 package template
5
6 import (
7 "fmt"
8 "reflect"
9 )
10
11 var (
12 errorType = reflect.TypeOf((*error)(nil)).Elem()
13 fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
14 )
15
16
17
18
19 func Indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
20 for ; v.Kind() == reflect.Pointer || v.Kind() == reflect.Interface; v = v.Elem() {
21 if v.IsNil() {
22 return v, true
23 }
24 if v.Kind() == reflect.Interface && v.NumMethod() > 0 {
25 break
26 }
27 }
28 return v, false
29 }
30
31
32
33 func PrintableValue(v reflect.Value) (interface{}, bool) {
34 if v.Kind() == reflect.Pointer {
35 v, _ = Indirect(v)
36 }
37 if !v.IsValid() {
38 return "<no value>", true
39 }
40
41 if !v.Type().Implements(errorType) && !v.Type().Implements(fmtStringerType) {
42 if v.CanAddr() && (reflect.PointerTo(v.Type()).Implements(errorType) || reflect.PointerTo(v.Type()).Implements(fmtStringerType)) {
43 v = v.Addr()
44 } else {
45 switch v.Kind() {
46 case reflect.Chan, reflect.Func:
47 return nil, false
48 }
49 }
50 }
51 return v.Interface(), true
52 }
53
View as plain text