dumpPtr handles formatting of pointers by indirecting them as necessary.
(v reflect.Value)
| 79 | |
| 80 | // dumpPtr handles formatting of pointers by indirecting them as necessary. |
| 81 | func (d *dumpState) dumpPtr(v reflect.Value) { |
| 82 | // Remove pointers at or below the current depth from map used to detect |
| 83 | // circular refs. |
| 84 | for k, depth := range d.pointers { |
| 85 | if depth >= d.depth { |
| 86 | delete(d.pointers, k) |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | // Keep list of all dereferenced pointers to show later. |
| 91 | pointerChain := make([]uintptr, 0) |
| 92 | |
| 93 | // Figure out how many levels of indirection there are by dereferencing |
| 94 | // pointers and unpacking interfaces down the chain while detecting circular |
| 95 | // references. |
| 96 | nilFound := false |
| 97 | cycleFound := false |
| 98 | indirects := 0 |
| 99 | ve := v |
| 100 | for ve.Kind() == reflect.Ptr { |
| 101 | if ve.IsNil() { |
| 102 | nilFound = true |
| 103 | break |
| 104 | } |
| 105 | indirects++ |
| 106 | addr := ve.Pointer() |
| 107 | pointerChain = append(pointerChain, addr) |
| 108 | if pd, ok := d.pointers[addr]; ok && pd < d.depth { |
| 109 | cycleFound = true |
| 110 | indirects-- |
| 111 | break |
| 112 | } |
| 113 | d.pointers[addr] = d.depth |
| 114 | |
| 115 | ve = ve.Elem() |
| 116 | if ve.Kind() == reflect.Interface { |
| 117 | if ve.IsNil() { |
| 118 | nilFound = true |
| 119 | break |
| 120 | } |
| 121 | ve = ve.Elem() |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | // Display type information. |
| 126 | d.w.Write(openParenBytes) |
| 127 | d.w.Write(bytes.Repeat(asteriskBytes, indirects)) |
| 128 | d.w.Write([]byte(ve.Type().String())) |
| 129 | d.w.Write(closeParenBytes) |
| 130 | |
| 131 | // Display pointer information. |
| 132 | if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 { |
| 133 | d.w.Write(openParenBytes) |
| 134 | for i, addr := range pointerChain { |
| 135 | if i > 0 { |
| 136 | d.w.Write(pointerChainBytes) |
| 137 | } |
| 138 | printHexPtr(d.w, addr) |