Skip to content

Instantly share code, notes, and snippets.

@travisjeffery
Last active November 2, 2017 17:57
Show Gist options
  • Select an option

  • Save travisjeffery/07ef25b7e90bae64c4b9928ed8a2a27f to your computer and use it in GitHub Desktop.

Select an option

Save travisjeffery/07ef25b7e90bae64c4b9928ed8a2a27f to your computer and use it in GitHub Desktop.
// error.go
// Copyright 2016 The Upspin Authors. All rights reserved.
// populateStack uses the runtime to populate the Error's stack struct with
// information about the current stack.
func (e *Error) populateStack() {
e.Stack = &Stack{Callers: callers()}
}
// printStack formats and prints the stack for this Error to the given buffer.
// It should be called from the Error's Error method.
func (e *Error) printStack(b *bytes.Buffer) {
if e.Stack == nil {
return
}
printCallers := callers()
// Iterate backward through e.Stack.Callers (the last in the stack is the
// earliest call, such as main) skipping over the PCs that are shared
// by the error stack and by this function call stack, printing the
// names of the functions and their file names and line numbers.
var prev string // the name of the last-seen function
var diff bool // do the print and error call stacks differ now?
for i := 0; i < len(e.Stack.Callers); i++ {
thisFrame := frame(e.Stack.Callers, i)
name := thisFrame.Func.Name()
if !diff && i < len(printCallers) {
if name == frame(printCallers, i).Func.Name() {
// both stacks share this PC, skip it.
continue
}
// No match, don't consider printCallers again.
diff = true
}
// Don't print the same function twice.
// (Can happen when multiple error stacks have been coalesced.)
if name == prev {
continue
}
// Find the uncommon prefix between this and the previous
// function name, separating by dots and slashes.
trim := 0
for {
j := strings.IndexAny(name[trim:], "./")
if j < 0 {
break
}
if !strings.HasPrefix(prev, name[:j+trim]) {
break
}
trim += j + 1 // skip over the separator
}
// Do the printing.
pad(b, separator)
fmt.Fprintf(b, "%v:%d: ", thisFrame.File, thisFrame.Line)
if trim > 0 {
b.WriteString("...")
}
b.WriteString(name[trim:])
prev = name
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment