gitee.com/hongliu9527/go-tools@v0.0.8/errors/gerror/gerror_api_stack.go (about)

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