forked from kakuilan/kgo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdebug.go
138 lines (117 loc) · 3.54 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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package kgo
import (
"errors"
"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 stack dump ===\n%s\n=== END 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...)
}
// GetFuncNames 获取变量的所有(公开的)函数名.
func (kd *LkkDebug) GetFuncNames(obj interface{}) (res []string) {
return getFuncNames(obj)
}
// WrapError 错误包裹.
func (ks *LkkDebug) WrapError(err error, args ...interface{}) (res error) {
num := len(args)
if err == nil && num == 0 {
res = errors.New("[WrapError] parameter error")
} else if err != nil && num == 0 {
res = err
} else {
var msg []string
for _, v := range args {
msg = append(msg, toStr(v))
}
if err != nil {
msg = append(msg, fmt.Sprintf("last error: %s", err.Error()))
}
res = errors.New(strings.Join(msg, "\r\n"))
}
return
}