handleMethods attempts to call the Error and String methods on the underlying type the passed reflect.Value represents and outputs the result to Writer w. It handles panics in any called methods by catching and displaying the error as the formatted value.
(cs *ConfigState, w io.Writer, v reflect.Value)
| 83 | // It handles panics in any called methods by catching and displaying the error |
| 84 | // as the formatted value. |
| 85 | func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) { |
| 86 | // We need an interface to check if the type implements the error or |
| 87 | // Stringer interface. However, the reflect package won't give us an |
| 88 | // interface on certain things like unexported struct fields in order |
| 89 | // to enforce visibility rules. We use unsafe, when it's available, |
| 90 | // to bypass these restrictions since this package does not mutate the |
| 91 | // values. |
| 92 | if !v.CanInterface() { |
| 93 | if UnsafeDisabled { |
| 94 | return false |
| 95 | } |
| 96 | |
| 97 | v = unsafeReflectValue(v) |
| 98 | } |
| 99 | |
| 100 | // Choose whether or not to do error and Stringer interface lookups against |
| 101 | // the base type or a pointer to the base type depending on settings. |
| 102 | // Technically calling one of these methods with a pointer receiver can |
| 103 | // mutate the value, however, types which choose to satisfy an error or |
| 104 | // Stringer interface with a pointer receiver should not be mutating their |
| 105 | // state inside these interface methods. |
| 106 | if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() { |
| 107 | v = unsafeReflectValue(v) |
| 108 | } |
| 109 | if v.CanAddr() { |
| 110 | v = v.Addr() |
| 111 | } |
| 112 | |
| 113 | // Is it an error or Stringer? |
| 114 | switch iface := v.Interface().(type) { |
| 115 | case error: |
| 116 | defer catchPanic(w, v) |
| 117 | if cs.ContinueOnMethod { |
| 118 | w.Write(openParenBytes) |
| 119 | w.Write([]byte(iface.Error())) |
| 120 | w.Write(closeParenBytes) |
| 121 | w.Write(spaceBytes) |
| 122 | return false |
| 123 | } |
| 124 | |
| 125 | w.Write([]byte(iface.Error())) |
| 126 | return true |
| 127 | |
| 128 | case fmt.Stringer: |
| 129 | defer catchPanic(w, v) |
| 130 | if cs.ContinueOnMethod { |
| 131 | w.Write(openParenBytes) |
| 132 | w.Write([]byte(iface.String())) |
| 133 | w.Write(closeParenBytes) |
| 134 | w.Write(spaceBytes) |
| 135 | return false |
| 136 | } |
| 137 | w.Write([]byte(iface.String())) |
| 138 | return true |
| 139 | } |
| 140 | return false |
| 141 | } |
| 142 |
no test coverage detected
searching dependent graphs…