|
1 | 1 | package errors |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "bytes" |
4 | 5 | "fmt" |
5 | 6 | "io" |
6 | 7 | "path" |
@@ -98,23 +99,50 @@ type StackTrace []Frame |
98 | 99 | // |
99 | 100 | // %+v Prints filename, function, and line number for each Frame in the stack. |
100 | 101 | func (st StackTrace) Format(s fmt.State, verb rune) { |
| 102 | + var b bytes.Buffer |
101 | 103 | switch verb { |
102 | 104 | case 'v': |
103 | 105 | switch { |
104 | 106 | case s.Flag('+'): |
| 107 | + b.Grow(len(st) * stackMinLen) |
105 | 108 | for _, f := range st { |
106 | | - fmt.Fprintf(s, "\n%+v", f) |
| 109 | + b.WriteByte('\n') |
| 110 | + f.format(&b, s, verb) |
107 | 111 | } |
108 | 112 | case s.Flag('#'): |
109 | | - fmt.Fprintf(s, "%#v", []Frame(st)) |
| 113 | + fmt.Fprintf(&b, "%#v", []Frame(st)) |
110 | 114 | default: |
111 | | - fmt.Fprintf(s, "%v", []Frame(st)) |
| 115 | + st.formatSlice(&b, s, verb) |
112 | 116 | } |
113 | 117 | case 's': |
114 | | - fmt.Fprintf(s, "%s", []Frame(st)) |
| 118 | + st.formatSlice(&b, s, verb) |
115 | 119 | } |
| 120 | + io.Copy(s, &b) |
116 | 121 | } |
117 | 122 |
|
| 123 | +// formatSlice will format this StackTrace into the given buffer as a slice of |
| 124 | +// Frame, only valid when called with '%s' or '%v'. |
| 125 | +func (st StackTrace) formatSlice(b *bytes.Buffer, s fmt.State, verb rune) { |
| 126 | + b.WriteByte('[') |
| 127 | + if len(st) == 0 { |
| 128 | + b.WriteByte(']') |
| 129 | + return |
| 130 | + } |
| 131 | + |
| 132 | + b.Grow(len(st) * (stackMinLen / 4)) |
| 133 | + st[0].format(b, s, verb) |
| 134 | + for _, fr := range st[1:] { |
| 135 | + b.WriteByte(' ') |
| 136 | + fr.format(b, s, verb) |
| 137 | + } |
| 138 | + b.WriteByte(']') |
| 139 | +} |
| 140 | + |
| 141 | +// stackMinLen is a best-guess at the minimum length of a stack trace. It |
| 142 | +// doesn't need to be exact, just give a good enough head start for the buffer |
| 143 | +// to avoid the expensive early growth. |
| 144 | +const stackMinLen = 96 |
| 145 | + |
118 | 146 | // stack represents a stack of program counters. |
119 | 147 | type stack []uintptr |
120 | 148 |
|
|
0 commit comments