github.com/biogo/biogo@v1.0.4/errors/errors.go (about) 1 // Copyright ©2011-2013 The bíogo Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package errors supports generic rich error reporting. 6 // 7 // This package is deprecated. Since it was written much better 8 // approaches have been developed. 9 package errors 10 11 import ( 12 "bytes" 13 "fmt" 14 "runtime" 15 "strings" 16 ) 17 18 // Type Error is the interface for rich error reporting supported by the 19 // errors package. 20 type Error interface { 21 // FileLine returns the file name and line number of caller 22 // stored at creation of the Error. 23 FileLine() (file string, line int) 24 25 // Trace returns a slice continuing the stack trace stored at 26 // creation of the Error. 27 Trace() (stack []*runtime.Func) 28 29 // Package returns the package name of the stored caller. 30 Package() string 31 32 // Function returns the function name of the stored caller. 33 Function() string 34 35 // Items returns any items retained by caller. 36 Items() []interface{} 37 38 // Tracef returns a formatted stack trace of the error 39 // extending depth frames into the stack, 0 indicates no limit. 40 Tracef(depth int) string 41 error 42 } 43 44 type errorBase struct { 45 *runtime.Func 46 pc []uintptr 47 message string 48 items []interface{} 49 } 50 51 // Make creates a new Error with message, storing information about the 52 // caller stack frame skip levels above the caller and any item that may 53 // be needed for handling the error. The number of frames stored is specified 54 // by the depth parameter. If depth is zero, Make will panic. 55 func Make(message string, skip, depth int, items ...interface{}) Error { 56 if depth == 0 { 57 panic("errors: zero trace depth") 58 } 59 err := &errorBase{ 60 pc: make([]uintptr, depth), 61 message: message, 62 items: items, 63 } 64 65 var n int 66 if n = runtime.Callers(skip+2, err.pc); n > 0 { 67 err.Func = runtime.FuncForPC(err.pc[0]) 68 } 69 err.pc = err.pc[:n] 70 71 return err 72 } 73 74 // Return the file name and line number of caller stored at creation of 75 // the Error. 76 func (err *errorBase) FileLine() (file string, line int) { 77 return err.Func.FileLine(err.pc[0]) 78 } 79 80 // Return a slice contining the stack trace stored at creation of the Error. 81 func (err *errorBase) Trace() (stack []*runtime.Func) { 82 stack = make([]*runtime.Func, len(err.pc)) 83 for i, pc := range err.pc { 84 stack[i] = runtime.FuncForPC(pc) 85 } 86 87 return 88 } 89 90 // Return the package name of the stored caller. 91 func (err *errorBase) Package() string { 92 caller := strings.Split(err.Func.Name(), ".") 93 return strings.Join(caller[0:len(caller)-1], ".") 94 } 95 96 // Return the function name of the stored caller. 97 func (err *errorBase) Function() string { 98 caller := strings.Split(err.Func.Name(), ".") 99 return caller[len(caller)-1] 100 } 101 102 // Return any items retained by caller. 103 func (err *errorBase) Items() []interface{} { return err.items } 104 105 // A formatted stack trace of the error extending depth frames into the 106 // stack, 0 indicates no limit. 107 func (err *errorBase) Tracef(depth int) string { 108 var last, name string 109 b := &bytes.Buffer{} 110 fmt.Fprintf(b, "Trace: %s:\n", err.message) 111 for i, frame := range err.Trace() { 112 if depth > 0 && i >= depth { 113 break 114 } 115 file, line := frame.FileLine(err.pc[i]) 116 if name = frame.Name(); name != last { 117 fmt.Fprintf(b, "\n %s:\n", frame.Name()) 118 } 119 last = name 120 fmt.Fprintf(b, "\t%s#L=%d\n", file, line) 121 } 122 123 return string(b.Bytes()) 124 } 125 126 // Satisfy the error interface. 127 func (err *errorBase) Error() string { 128 return err.message 129 }