package conv // stolen from the Go standard library, text/template package. import ( "fmt" "reflect" ) var ( errorType = reflect.TypeOf((*error)(nil)).Elem() fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() ) // printableValue returns the, possibly indirected, interface value inside v that // is best for a call to formatted printer. func printableValue(v reflect.Value) (any, bool) { if v.Kind() == reflect.Ptr { v, _ = indirect(v) // fmt.Fprint handles nil. } if !v.IsValid() { return "", true } if !v.Type().Implements(errorType) && !v.Type().Implements(fmtStringerType) { if v.CanAddr() && (reflect.PointerTo(v.Type()).Implements(errorType) || reflect.PointerTo(v.Type()).Implements(fmtStringerType)) { v = v.Addr() } else { switch v.Kind() { case reflect.Chan, reflect.Func: return nil, false } } } return v.Interface(), true } // indirect returns the item at the end of indirection, and a bool to indicate if it's nil. func indirect(v reflect.Value) (rv reflect.Value, isNil bool) { for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() { if v.IsNil() { return v, true } } return v, false }