layerString outputs, recursively, a layer in a "smart" way. See docs for LayerString for more details. Params: i - value to write out anonymous: if we're currently recursing an anonymous member of a struct writeSpace: if we've already written a value in a struct, and need to write a space before
(v reflect.Value, anonymous bool, writeSpace bool)
| 253 | // write a space before writing more. This happens when we write various |
| 254 | // anonymous values, and need to keep writing more. |
| 255 | func layerString(v reflect.Value, anonymous bool, writeSpace bool) string { |
| 256 | // Let String() functions take precedence. |
| 257 | if v.CanInterface() { |
| 258 | if s, ok := v.Interface().(fmt.Stringer); ok { |
| 259 | return s.String() |
| 260 | } |
| 261 | } |
| 262 | // Reflect, and spit out all the exported fields as key=value. |
| 263 | switch v.Type().Kind() { |
| 264 | case reflect.Interface, reflect.Ptr: |
| 265 | if v.IsNil() { |
| 266 | return "nil" |
| 267 | } |
| 268 | r := v.Elem() |
| 269 | return layerString(r, anonymous, writeSpace) |
| 270 | case reflect.Struct: |
| 271 | var b bytes.Buffer |
| 272 | typ := v.Type() |
| 273 | if !anonymous { |
| 274 | b.WriteByte('{') |
| 275 | } |
| 276 | for i := 0; i < v.NumField(); i++ { |
| 277 | // Check if this is upper-case. |
| 278 | ftype := typ.Field(i) |
| 279 | f := v.Field(i) |
| 280 | if ftype.Anonymous { |
| 281 | anonStr := layerString(f, true, writeSpace) |
| 282 | writeSpace = writeSpace || anonStr != "" |
| 283 | b.WriteString(anonStr) |
| 284 | } else if ftype.PkgPath == "" { // exported |
| 285 | if writeSpace { |
| 286 | b.WriteByte(' ') |
| 287 | } |
| 288 | writeSpace = true |
| 289 | fmt.Fprintf(&b, "%s=%s", typ.Field(i).Name, layerString(f, false, writeSpace)) |
| 290 | } |
| 291 | } |
| 292 | if !anonymous { |
| 293 | b.WriteByte('}') |
| 294 | } |
| 295 | return b.String() |
| 296 | case reflect.Slice: |
| 297 | var b bytes.Buffer |
| 298 | b.WriteByte('[') |
| 299 | if v.Len() > 4 { |
| 300 | fmt.Fprintf(&b, "..%d..", v.Len()) |
| 301 | } else { |
| 302 | for j := 0; j < v.Len(); j++ { |
| 303 | if j != 0 { |
| 304 | b.WriteString(", ") |
| 305 | } |
| 306 | b.WriteString(layerString(v.Index(j), false, false)) |
| 307 | } |
| 308 | } |
| 309 | b.WriteByte(']') |
| 310 | return b.String() |
| 311 | } |
| 312 | return fmt.Sprintf("%v", v.Interface()) |
searching dependent graphs…