github.com/gogf/gf/v2@v2.7.4/errors/gerror/gerror_api_stack.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/gogf/gf.
     6  
     7  package gerror
     8  
     9  import (
    10  	"errors"
    11  	"runtime"
    12  )
    13  
    14  // stack represents a stack of program counters.
    15  type stack []uintptr
    16  
    17  const (
    18  	// maxStackDepth marks the max stack depth for error back traces.
    19  	maxStackDepth = 64
    20  )
    21  
    22  // Cause returns the root cause error of `err`.
    23  func Cause(err error) error {
    24  	if err == nil {
    25  		return nil
    26  	}
    27  	if e, ok := err.(ICause); ok {
    28  		return e.Cause()
    29  	}
    30  	if e, ok := err.(IUnwrap); ok {
    31  		return Cause(e.Unwrap())
    32  	}
    33  	return err
    34  }
    35  
    36  // Stack returns the stack callers as string.
    37  // It returns the error string directly if the `err` does not support stacks.
    38  func Stack(err error) string {
    39  	if err == nil {
    40  		return ""
    41  	}
    42  	if e, ok := err.(IStack); ok {
    43  		return e.Stack()
    44  	}
    45  	return err.Error()
    46  }
    47  
    48  // Current creates and returns the current level error.
    49  // It returns nil if current level error is nil.
    50  func Current(err error) error {
    51  	if err == nil {
    52  		return nil
    53  	}
    54  	if e, ok := err.(ICurrent); ok {
    55  		return e.Current()
    56  	}
    57  	return err
    58  }
    59  
    60  // Unwrap returns the next level error.
    61  // It returns nil if current level error or the next level error is nil.
    62  func Unwrap(err error) error {
    63  	if err == nil {
    64  		return nil
    65  	}
    66  	if e, ok := err.(IUnwrap); ok {
    67  		return e.Unwrap()
    68  	}
    69  	return nil
    70  }
    71  
    72  // HasStack checks and reports whether `err` implemented interface `gerror.IStack`.
    73  func HasStack(err error) bool {
    74  	_, ok := err.(IStack)
    75  	return ok
    76  }
    77  
    78  // Equal reports whether current error `err` equals to error `target`.
    79  // Please note that, in default comparison logic for `Error`,
    80  // the errors are considered the same if both the `code` and `text` of them are the same.
    81  func Equal(err, target error) bool {
    82  	if err == target {
    83  		return true
    84  	}
    85  	if e, ok := err.(IEqual); ok {
    86  		return e.Equal(target)
    87  	}
    88  	if e, ok := target.(IEqual); ok {
    89  		return e.Equal(err)
    90  	}
    91  	return false
    92  }
    93  
    94  // Is reports whether current error `err` has error `target` in its chaining errors.
    95  // There's similar function HasError which is designed and implemented early before errors.Is of go stdlib.
    96  // It is now alias of errors.Is of go stdlib, to guarantee the same performance as go stdlib.
    97  func Is(err, target error) bool {
    98  	return errors.Is(err, target)
    99  }
   100  
   101  // HasError performs as Is.
   102  // This function is designed and implemented early before errors.Is of go stdlib.
   103  // Deprecated: use Is instead.
   104  func HasError(err, target error) bool {
   105  	return errors.Is(err, target)
   106  }
   107  
   108  // callers returns the stack callers.
   109  // Note that it here just retrieves the caller memory address array not the caller information.
   110  func callers(skip ...int) stack {
   111  	var (
   112  		pcs [maxStackDepth]uintptr
   113  		n   = 3
   114  	)
   115  	if len(skip) > 0 {
   116  		n += skip[0]
   117  	}
   118  	return pcs[:runtime.Callers(n, pcs[:])]
   119  }