github.com/wangyougui/gf/v2@v2.6.5/errors/gerror/gerror_error.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/wangyougui/gf.
     6  
     7  package gerror
     8  
     9  import (
    10  	"errors"
    11  	"fmt"
    12  	"runtime"
    13  	"strings"
    14  
    15  	"github.com/wangyougui/gf/v2/errors/gcode"
    16  )
    17  
    18  // Error is custom error for additional features.
    19  type Error struct {
    20  	error error      // Wrapped error.
    21  	stack stack      // Stack array, which records the stack information when this error is created or wrapped.
    22  	text  string     // Custom Error text when Error is created, might be empty when its code is not nil.
    23  	code  gcode.Code // Error code if necessary.
    24  }
    25  
    26  const (
    27  	// Filtering key for current error module paths.
    28  	stackFilterKeyLocal = "/errors/gerror/gerror"
    29  )
    30  
    31  var (
    32  	// goRootForFilter is used for stack filtering in development environment purpose.
    33  	goRootForFilter = runtime.GOROOT()
    34  )
    35  
    36  func init() {
    37  	if goRootForFilter != "" {
    38  		goRootForFilter = strings.ReplaceAll(goRootForFilter, "\\", "/")
    39  	}
    40  }
    41  
    42  // Error implements the interface of Error, it returns all the error as string.
    43  func (err *Error) Error() string {
    44  	if err == nil {
    45  		return ""
    46  	}
    47  	errStr := err.text
    48  	if errStr == "" && err.code != nil {
    49  		errStr = err.code.Message()
    50  	}
    51  	if err.error != nil {
    52  		if errStr != "" {
    53  			errStr += ": "
    54  		}
    55  		errStr += err.error.Error()
    56  	}
    57  	return errStr
    58  }
    59  
    60  // Cause returns the root cause error.
    61  func (err *Error) Cause() error {
    62  	if err == nil {
    63  		return nil
    64  	}
    65  	loop := err
    66  	for loop != nil {
    67  		if loop.error != nil {
    68  			if e, ok := loop.error.(*Error); ok {
    69  				// Internal Error struct.
    70  				loop = e
    71  			} else if e, ok := loop.error.(ICause); ok {
    72  				// Other Error that implements ApiCause interface.
    73  				return e.Cause()
    74  			} else {
    75  				return loop.error
    76  			}
    77  		} else {
    78  			// return loop
    79  			//
    80  			// To be compatible with Case of https://github.com/pkg/errors.
    81  			return errors.New(loop.text)
    82  		}
    83  	}
    84  	return nil
    85  }
    86  
    87  // Current creates and returns the current level error.
    88  // It returns nil if current level error is nil.
    89  func (err *Error) Current() error {
    90  	if err == nil {
    91  		return nil
    92  	}
    93  	return &Error{
    94  		error: nil,
    95  		stack: err.stack,
    96  		text:  err.text,
    97  		code:  err.code,
    98  	}
    99  }
   100  
   101  // Unwrap is alias of function `Next`.
   102  // It is just for implements for stdlib errors.Unwrap from Go version 1.17.
   103  func (err *Error) Unwrap() error {
   104  	if err == nil {
   105  		return nil
   106  	}
   107  	return err.error
   108  }
   109  
   110  // Equal reports whether current error `err` equals to error `target`.
   111  // Please note that, in default comparison for `Error`,
   112  // the errors are considered the same if both the `code` and `text` of them are the same.
   113  func (err *Error) Equal(target error) bool {
   114  	if err == target {
   115  		return true
   116  	}
   117  	// Code should be the same.
   118  	// Note that if both errors have `nil` code, they are also considered equal.
   119  	if err.code != Code(target) {
   120  		return false
   121  	}
   122  	// Text should be the same.
   123  	if err.text != fmt.Sprintf(`%-s`, target) {
   124  		return false
   125  	}
   126  	return true
   127  }
   128  
   129  // Is reports whether current error `err` has error `target` in its chaining errors.
   130  // It is just for implements for stdlib errors.Is from Go version 1.17.
   131  func (err *Error) Is(target error) bool {
   132  	if Equal(err, target) {
   133  		return true
   134  	}
   135  	nextErr := err.Unwrap()
   136  	if nextErr == nil {
   137  		return false
   138  	}
   139  	if Equal(nextErr, target) {
   140  		return true
   141  	}
   142  	if e, ok := nextErr.(IIs); ok {
   143  		return e.Is(target)
   144  	}
   145  	return false
   146  }