github.com/PandaGoAdmin/utils@v0.0.0-20211208134815-d5461603a00f/debug.go (about)

     1  package kgo
     2  
     3  import (
     4  	"fmt"
     5  	"go/parser"
     6  	"go/token"
     7  	"path/filepath"
     8  	"reflect"
     9  	"runtime"
    10  	"strings"
    11  )
    12  
    13  // DumpPrint 打印调试变量.
    14  func (ks *LkkDebug) DumpPrint(vs ...interface{}) {
    15  	dumpPrint(vs...)
    16  }
    17  
    18  // DumpStacks 打印堆栈信息.
    19  func (kd *LkkDebug) DumpStacks() {
    20  	buf := make([]byte, 16384)
    21  	buf = buf[:runtime.Stack(buf, true)]
    22  	fmt.Printf("=== BEGIN goroutine stack dump ===\n%s\n=== END goroutine stack dump ===\n\n", buf)
    23  }
    24  
    25  // GetCallName 获取调用的方法名称;f为目标方法;onlyFun为true时仅返回方法,不包括包名.
    26  func (kd *LkkDebug) GetCallName(f interface{}, onlyFun bool) string {
    27  	var funcObj *runtime.Func
    28  	r := reflectPtr(reflect.ValueOf(f))
    29  	switch r.Kind() {
    30  	case reflect.Invalid:
    31  		// Skip this function, and fetch the PC and file for its parent
    32  		pc, _, _, _ := runtime.Caller(1)
    33  		// Retrieve a Function object this functions parent
    34  		funcObj = runtime.FuncForPC(pc)
    35  	case reflect.Func:
    36  		funcObj = runtime.FuncForPC(r.Pointer())
    37  	default:
    38  		return ""
    39  	}
    40  
    41  	name := funcObj.Name()
    42  	if onlyFun {
    43  		// extract just the function name (and not the module path)
    44  		return strings.TrimPrefix(filepath.Ext(name), ".")
    45  	}
    46  
    47  	return name
    48  }
    49  
    50  // GetCallFile 获取调用方法的文件路径.
    51  func (kd *LkkDebug) GetCallFile() string {
    52  	_, file, _, _ := runtime.Caller(1)
    53  	return file
    54  }
    55  
    56  // GetCallDir 获取调用方法的文件目录.
    57  func (kd *LkkDebug) GetCallDir() string {
    58  	return filepath.Dir(kd.GetCallFile())
    59  }
    60  
    61  // GetCallLine 获取调用方法的行号.
    62  func (kd *LkkDebug) GetCallLine() int {
    63  	// Skip this function, and fetch the PC and file for its parent
    64  	_, _, line, _ := runtime.Caller(1)
    65  	return line
    66  }
    67  
    68  // GetCallPackage 获取调用方法或调用文件的包名.callFile为调用文件路径.
    69  func (kd *LkkDebug) GetCallPackage(callFile ...string) string {
    70  	var sourceFile string
    71  	if len(callFile) == 0 {
    72  		sourceFile = kd.GetCallFile()
    73  	} else {
    74  		sourceFile = callFile[0]
    75  	}
    76  
    77  	fset := token.NewFileSet()
    78  	astFile, err := parser.ParseFile(fset, sourceFile, nil, parser.PackageClauseOnly)
    79  	if err != nil || astFile.Name == nil {
    80  		return ""
    81  	}
    82  
    83  	return astFile.Name.Name
    84  }
    85  
    86  // HasMethod 检查对象t是否具有method方法.
    87  func (kd *LkkDebug) HasMethod(t interface{}, method string) bool {
    88  	_, err := methodExists(t, method)
    89  	return err == nil
    90  }
    91  
    92  // GetMethod 获取对象t中的method方法.
    93  // 注意:返回的方法中的第一个参数是接收者.
    94  // 所以,调用返回的方法时,必须将接收者作为第一个参数传递.
    95  func (kd *LkkDebug) GetMethod(t interface{}, method string) interface{} {
    96  	return getMethod(t, method)
    97  }
    98  
    99  // CallMethod 调用对象的方法.
   100  // 若执行成功,则结果是该方法的返回结果;
   101  // 否则返回(nil, error).
   102  func (kd *LkkDebug) CallMethod(t interface{}, method string, args ...interface{}) ([]interface{}, error) {
   103  	m := kd.GetMethod(t, method)
   104  	if m == nil {
   105  		return nil, fmt.Errorf("[CallMethod] The %#v have no method: %s", t, method)
   106  	}
   107  
   108  	return CallFunc(m, args...)
   109  }
   110  
   111  // GetFuncNames 获取变量的所有(公开的)函数名.
   112  func (kd *LkkDebug) GetFuncNames(obj interface{}) (res []string) {
   113  	return getFuncNames(obj)
   114  }