From f06639a51d4e9cc94a12d0b36293afd46a355b14 Mon Sep 17 00:00:00 2001 From: Denis Date: Sat, 13 Nov 2021 12:12:39 +0300 Subject: [PATCH] add external PR:https://github.com/pkg/errors/pull/198 --- .gitignore | 1 + stack.go | 36 +++++++++++++++++++++++++----------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index daf913b1..25e241ae 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ _testmain.go *.exe *.test *.prof +.idea diff --git a/stack.go b/stack.go index 3206506e..a04d7c46 100644 --- a/stack.go +++ b/stack.go @@ -1,6 +1,7 @@ package errors import ( + "bytes" "fmt" "io" "path" @@ -49,6 +50,8 @@ func (f Frame) name() string { return fn.Name() } +func (f Frame) Format(s fmt.State, verb rune) { f.format(s, s, verb) } + // Format formats the frame according to the fmt.Formatter interface. // // %s source file @@ -61,25 +64,25 @@ func (f Frame) name() string { // %+s function name and path of source file relative to the compile time // GOPATH separated by \n\t (\n\t) // %+v equivalent to %+s:%d -func (f Frame) Format(s fmt.State, verb rune) { +func (f Frame) format(w io.Writer, s fmt.State, verb rune) { switch verb { case 's': switch { case s.Flag('+'): - io.WriteString(s, f.name()) - io.WriteString(s, "\n\t") - io.WriteString(s, f.file()) + io.WriteString(w, f.name()) + io.WriteString(w, "\n\t") + io.WriteString(w, f.file()) default: - io.WriteString(s, path.Base(f.file())) + io.WriteString(w, path.Base(f.file())) } case 'd': - io.WriteString(s, strconv.Itoa(f.line())) + io.WriteString(w, strconv.Itoa(f.line())) case 'n': - io.WriteString(s, funcname(f.name())) + io.WriteString(w, funcname(f.name())) case 'v': - f.Format(s, 's') - io.WriteString(s, ":") - f.Format(s, 'd') + f.format(w, s, 's') + io.WriteString(w, ":") + f.format(w, s, 'd') } } @@ -141,11 +144,22 @@ func (st StackTrace) formatSlice(s fmt.State, verb rune) { // stack represents a stack of program counters. type stack []uintptr +// stackMinLen is a best-guess at the minimum length of a stack trace. It +// doesn't need to be exact, just give a good enough head start for the buffer +// to avoid the expensive early growth. +const stackMinLen = 96 + func (s *stack) Format(st fmt.State, verb rune) { if verb == 'v' && st.Flag('+') { + var b = &bytes.Buffer{} + b.Grow(len(*s) * stackMinLen) + for i := range *s { - fmt.Fprintf(st, "\n%+v", Frame((*s)[i])) + b.WriteByte('\n') + Frame((*s)[i]).format(b, st, verb) } + + io.Copy(st, b) } }