-
Notifications
You must be signed in to change notification settings - Fork 0
/
source.go
120 lines (103 loc) · 2.61 KB
/
source.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
// SPDX-FileCopyrightText: 2020-2024 caixw
//
// SPDX-License-Identifier: MIT
// Package source 提供与 Go 源码相关的一些操作
package source
import (
"bytes"
"io"
"path/filepath"
"runtime"
"strconv"
"strings"
"github.com/issue9/errwrap"
)
// CurrentPath 获取`调用者`所在目录的路径
//
// 类似于部分语言的的 __DIR__ + "/" + path
func CurrentPath(path string) string {
_, fi, _, _ := runtime.Caller(1)
return filepath.Join(filepath.Dir(fi), path)
}
// CurrentDir 获取`调用者`所在的目录
//
// 相当于部分语言的 __DIR__
func CurrentDir() string {
_, fi, _, _ := runtime.Caller(1)
return filepath.Dir(fi)
}
// CurrentFile 获取`调用者`所在的文件
//
// 相当于部分语言的 __FILE__
func CurrentFile() string {
_, fi, _, _ := runtime.Caller(1)
return fi
}
// CurrentLine 获取`调用者`所在的行
//
// 相当于部分语言的 __LINE__
func CurrentLine() int {
_, _, line, _ := runtime.Caller(1)
return line
}
// CurrentLocation 获取`调用者`当前的位置信息
func CurrentLocation() (path string, line int) {
_, path, line, _ = runtime.Caller(1)
return path, line
}
// CurrentFunction 获取`调用者`所在的函数名
//
// 相当于部分语言的 __FUNCTION__
func CurrentFunction() string {
pc, _, _, _ := runtime.Caller(1)
name := runtime.FuncForPC(pc).Name()
index := strings.LastIndexByte(name, '.')
if index > 0 {
name = name[index+1:]
}
return name
}
// Stack 返回调用堆栈信息
//
// skip 需要忽略的内容。
//
// - 1 表示 Stack 自身;
// - 2 表示 Stack 的调用者,以此类推;
//
// msg 表示需要输出的额外信息;
func Stack(skip int, ignoreRuntime bool, msg ...any) string {
buf := &bytes.Buffer{}
DumpStack(buf, skip+1, ignoreRuntime, msg...)
return buf.String()
}
// DumpStack 将调用的堆栈信息写入 w
//
// skip 需要忽略的内容。
//
// - 1 表示 Stack 自身;
// - 2 表示 Stack 的调用者,以此类推;
//
// ignoreRuntime 表示是否不显示 runtime 下的系统调用信息;
// msg 表示需要输出的额外信息;
func DumpStack(w io.Writer, skip int, ignoreRuntime bool, msg ...any) {
pc := make([]uintptr, 10)
n := runtime.Callers(skip, pc)
if n == 0 {
return
}
pc = pc[:n]
frames := runtime.CallersFrames(pc)
buf := errwrap.Writer{Writer: w}
buf.Println(msg...)
for {
frame, more := frames.Next()
if !more {
break
}
if ignoreRuntime && strings.Contains(frame.File, "runtime/") {
continue
}
buf.WString(frame.Function).WByte('\n').
WByte('\t').WString(frame.File).WByte(':').WString(strconv.Itoa(frame.Line)).WByte('\n')
}
}