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