FormatValue prints the reflect.Value, taking extra care to avoid descending into pointers already in ptrs. As pointers are visited, ptrs is also updated.
(v reflect.Value, parentKind reflect.Kind, ptrs *pointerReferences)
| 112 | // FormatValue prints the reflect.Value, taking extra care to avoid descending |
| 113 | // into pointers already in ptrs. As pointers are visited, ptrs is also updated. |
| 114 | func (opts formatOptions) FormatValue(v reflect.Value, parentKind reflect.Kind, ptrs *pointerReferences) (out textNode) { |
| 115 | if !v.IsValid() { |
| 116 | return nil |
| 117 | } |
| 118 | t := v.Type() |
| 119 | |
| 120 | // Check slice element for cycles. |
| 121 | if parentKind == reflect.Slice { |
| 122 | ptrRef, visited := ptrs.Push(v.Addr()) |
| 123 | if visited { |
| 124 | return makeLeafReference(ptrRef, false) |
| 125 | } |
| 126 | defer ptrs.Pop() |
| 127 | defer func() { out = wrapTrunkReference(ptrRef, false, out) }() |
| 128 | } |
| 129 | |
| 130 | // Check whether there is an Error or String method to call. |
| 131 | if !opts.AvoidStringer && v.CanInterface() { |
| 132 | // Avoid calling Error or String methods on nil receivers since many |
| 133 | // implementations crash when doing so. |
| 134 | if (t.Kind() != reflect.Ptr && t.Kind() != reflect.Interface) || !v.IsNil() { |
| 135 | var prefix, strVal string |
| 136 | func() { |
| 137 | // Swallow and ignore any panics from String or Error. |
| 138 | defer func() { recover() }() |
| 139 | switch v := v.Interface().(type) { |
| 140 | case error: |
| 141 | strVal = v.Error() |
| 142 | prefix = "e" |
| 143 | case fmt.Stringer: |
| 144 | strVal = v.String() |
| 145 | prefix = "s" |
| 146 | } |
| 147 | }() |
| 148 | if prefix != "" { |
| 149 | return opts.formatString(prefix, strVal) |
| 150 | } |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | // Check whether to explicitly wrap the result with the type. |
| 155 | var skipType bool |
| 156 | defer func() { |
| 157 | if !skipType { |
| 158 | out = opts.FormatType(t, out) |
| 159 | } |
| 160 | }() |
| 161 | |
| 162 | switch t.Kind() { |
| 163 | case reflect.Bool: |
| 164 | return textLine(fmt.Sprint(v.Bool())) |
| 165 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: |
| 166 | return textLine(fmt.Sprint(v.Int())) |
| 167 | case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64: |
| 168 | return textLine(fmt.Sprint(v.Uint())) |
| 169 | case reflect.Uint8: |
| 170 | if parentKind == reflect.Slice || parentKind == reflect.Array { |
| 171 | return textLine(formatHex(v.Uint())) |
no test coverage detected