-
Notifications
You must be signed in to change notification settings - Fork 0
/
fn_utils.go
141 lines (125 loc) · 3.09 KB
/
fn_utils.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
139
140
141
package fn
import (
"bytes"
"errors"
"fmt"
"path/filepath"
"runtime"
"strings"
)
var (
//Nothing placeholder value
Nothing = struct{}{}
//ErrDuplicate for found duplicated value
ErrDuplicate = errors.New("duplicated value")
)
// Caller return call stack ,skip 1
func Caller() string {
pc, file, lineno, ok := runtime.Caller(1)
if ok {
return fmt.Sprintf("%s\t%s:%d", runtime.FuncForPC(pc).Name(), file, lineno)
}
return "unknown:unknown"
}
// CallerN return call stack skip n+1
func CallerN(n uint) string {
pc, file, lineno, ok := runtime.Caller(int(n) + 1)
if ok {
return fmt.Sprintf("%s\t%s:%d", runtime.FuncForPC(pc).Name(), file, lineno)
}
return "unknown:unknown"
}
// CallerFileN return call stack of file:line, skip n+1
func CallerFileN(n uint) string {
_, file, lineno, ok := runtime.Caller(int(n) + 1)
if ok {
return fmt.Sprintf("%s:%d", file, lineno)
}
return "unknown:unknown"
}
// CallerFile return call stack of file:line ,skip 1
func CallerFile() string {
_, file, lineno, ok := runtime.Caller(1)
if ok {
return fmt.Sprintf("%s:%d", file, lineno)
}
return "unknown:unknown"
}
// CallerShortFileN return call stack of file:line, skip n+1
func CallerShortFileN(n uint) string {
_, file, lineno, ok := runtime.Caller(int(n) + 1)
if ok {
return fmt.Sprintf("%s:%d", filepath.Base(file), lineno)
}
return "unknown:unknown"
}
// CallerShortFile return call stack of file:line ,skip 1
func CallerShortFile() string {
_, file, lineno, ok := runtime.Caller(1)
if ok {
return fmt.Sprintf("%s:%d", filepath.Base(file), lineno)
}
return "unknown:unknown"
}
// CallerStackN dump stack info of "function file:line"
func CallerStackN(n, s uint) string {
pc := make([]uintptr, s)
ok := runtime.Callers(int(n)+1, pc)
if ok > 0 {
frames := runtime.CallersFrames(pc)
var frame runtime.Frame
b := new(strings.Builder)
more := n > 0
for more {
frame, more = frames.Next()
b.WriteString(fmt.Sprintf("%s\t%s:%d\n", frame.Function, frame.File, frame.Line))
}
return b.String()
}
return "unknown:unknown"
}
// CallerShortStackN dump short stack "info of file:line"
func CallerShortStackN(n, s uint) string {
pc := make([]uintptr, s)
ok := runtime.Callers(int(n)+1, pc)
if ok > 0 {
frames := runtime.CallersFrames(pc)
var frame runtime.Frame
b := new(strings.Builder)
more := n > 0
for more {
frame, more = frames.Next()
b.WriteString(fmt.Sprintf("%s:%d\n", frame.File, frame.Line))
}
return b.String()
}
return "unknown:unknown"
}
type ErrLine struct {
Err error
Line string
}
func (e *ErrLine) Error() string {
return fmt.Sprintf("\n%s\t%s", e.Line, e.Err)
}
// NewErrLine create an Error with original caller line
func NewErrLine(err error, skip uint) error {
return &ErrLine{Err: err, Line: CallerFileN(skip)}
}
type ErrCombine struct {
Err []error
}
func (e *ErrCombine) Error() string {
var buffer bytes.Buffer
buf := &buffer
buf.Reset()
for _, e := range e.Err {
buf.WriteRune('\n')
buf.WriteString(e.Error())
}
return buf.String()
}
// NewErrCombine combine errors
func NewErrCombine(err ...error) error {
return &ErrCombine{Err: err}
}