| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- package errors
- import (
- "bytes"
- "fmt"
- "runtime"
- "strings"
- )
- // location represents a Location information of source code.
- type location struct {
- File string
- Line int
- }
- // String returns the string of Location with filename:line format.
- func (l *location) String() string {
- if len(l.File) == 0 {
- return ""
- }
- return fmt.Sprintf("%s:%d", l.File, l.Line)
- }
- // error2 represents an error.
- type error2 struct {
- Inner error
- Location *location
- Message string
- }
- // Error implements builtin.error interface.
- // It returns error message in a tree like format.
- func (e *error2) Error() string {
- return TreeMessage(e)
- }
- func locate(depth int) *location {
- _, file, line, _ := runtime.Caller(depth + 1)
- return &location{
- File: file,
- Line: line,
- }
- }
- // Equal detects whether the error is equal to a given error.
- // Errors are considered equal by this function if they are the same object, or if they both contain the same error inside.
- func Equal(err1 error, err2 error) bool {
- if err1 == err2 {
- return true
- }
- if v, ok := err1.(*error2); ok {
- return Equal(v.Inner, err2)
- }
- if v, ok := err2.(*error2); ok {
- return Equal(v.Inner, err1)
- }
- return false
- }
- // TreeMessage returns the errors message in a tree like format:
- // ├─ error message -> filename:line
- // | ├─ error message -> filename:line
- // | └─ error 3
- func TreeMessage(err error) string {
- if err == nil {
- return ""
- }
- var buf bytes.Buffer
- depth := 1
- for {
- if depth > 1 {
- buf.WriteString("\n|")
- buf.WriteString(strings.Repeat(" ", (depth-1)*3-1))
- }
- if e, ok := err.(*error2); ok {
- buf.WriteString("├─ " + e.Message + " -> " + e.Location.String())
- err = e.Inner
- } else {
- buf.WriteString("└─ " + err.Error())
- err = nil
- }
- if err == nil {
- break
- }
- depth++
- }
- return buf.String()
- }
- // New returns a new Error.
- // It's used to instead of built-in errors.New function.
- func New(message string) error {
- return &error2{
- Location: locate(1),
- Message: message,
- }
- }
- // Newf same as New, but with fmt.Printf-style parameters.
- func Newf(format string, args ...interface{}) error {
- return &error2{
- Location: locate(1),
- Message: fmt.Sprintf(format, args...),
- }
- }
- // Wrap returns a new wrapped Error.
- func Wrap(err error, message string) error {
- return &error2{
- Inner: err,
- Location: locate(2),
- Message: message,
- }
- }
- // Wrapf same as Wrap, but with fmt.Printf-style parameters.
- func Wrapf(err error, format string, args ...interface{}) error {
- return &error2{
- Inner: err,
- Location: locate(2),
- Message: fmt.Sprintf(format, args...),
- }
- }
|