github.com/hairyhenderson/gomplate/v4@v4.0.0-pre-2.0.20240520121557-362f058f0c93/conv/evalargs.go (about) 1 package conv 2 3 // stolen from the Go standard library, text/template package. 4 import ( 5 "fmt" 6 "reflect" 7 ) 8 9 var ( 10 errorType = reflect.TypeOf((*error)(nil)).Elem() 11 fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() 12 ) 13 14 // printableValue returns the, possibly indirected, interface value inside v that 15 // is best for a call to formatted printer. 16 func printableValue(v reflect.Value) (interface{}, bool) { 17 if v.Kind() == reflect.Ptr { 18 v, _ = indirect(v) // fmt.Fprint handles nil. 19 } 20 if !v.IsValid() { 21 return "<no value>", true 22 } 23 24 if !v.Type().Implements(errorType) && !v.Type().Implements(fmtStringerType) { 25 if v.CanAddr() && (reflect.PtrTo(v.Type()).Implements(errorType) || reflect.PtrTo(v.Type()).Implements(fmtStringerType)) { 26 v = v.Addr() 27 } else { 28 switch v.Kind() { 29 case reflect.Chan, reflect.Func: 30 return nil, false 31 } 32 } 33 } 34 return v.Interface(), true 35 } 36 37 // indirect returns the item at the end of indirection, and a bool to indicate if it's nil. 38 func indirect(v reflect.Value) (rv reflect.Value, isNil bool) { 39 for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() { 40 if v.IsNil() { 41 return v, true 42 } 43 } 44 return v, false 45 }