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