-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathruntime.go
138 lines (118 loc) · 3.24 KB
/
runtime.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 utils
import (
"context"
"log"
"os"
"os/signal"
"path/filepath"
"runtime"
"syscall"
_ "unsafe"
)
const (
// PtrSize 4 on 32-bit systems, 8 on 64-bit.
PtrSize = 4 << (^uintptr(0) >> 63)
)
var StackTraceBufferSize = 4 << 10
// RecoveryCallback 自定义恢复信息回调
type RecoveryCallback func(err interface{}, trace []byte)
// CallPath 运行时路径, 编译目录
// 假如: mklink E:\tmp\linkapp.exe D:\Fufu\Test\abc\app.exe
// 执行: E:\tmp\linkapp.exe
// CallPath: E:\Go\src\github.com\fufuok\utils\tmp\osext
func CallPath() string {
_, filename, _, ok := runtime.Caller(1)
if ok {
return filepath.Clean(filepath.Dir(filename))
}
return RunPath()
}
// RunPath 实际程序所在目录
// RunPath: E:\tmp
func RunPath() string {
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil {
// 调用时工作目录
dir, _ = os.Getwd()
return dir
}
return dir
}
// Executable 当前执行程序绝对路径
// true 时返回解析符号链接后的绝对路径
// Excutable: E:\tmp\linkapp.exe
// Excutable(true): D:\Fufu\Test\abc\app.exe
func Executable(evalSymlinks ...bool) string {
exe, _ := os.Executable()
if len(evalSymlinks) > 0 && evalSymlinks[0] {
exe, _ = filepath.EvalSymlinks(exe)
}
return filepath.Clean(exe)
}
// ExecutableDir 当前执行程序所在目录
// true 时返回解析符号链接后的目录
// ExcutableDir: E:\tmp
// ExcutableDir(true): D:\Fufu\Test\abc
func ExecutableDir(evalSymlinks ...bool) string {
return filepath.Dir(Executable(evalSymlinks...))
}
// Recover 从 panic 中恢复并记录堆栈信息
func Recover(cb ...RecoveryCallback) {
if err := recover(); err != nil {
buf := make([]byte, StackTraceBufferSize)
buf = buf[:runtime.Stack(buf, false)]
if len(cb) > 0 && cb[0] != nil {
cb[0](err, buf)
return
}
log.Printf("Recovery: %v\n--- Traceback:\n%v\n", err, B2S(buf))
}
}
// SafeGo 带 Recover 的 goroutine 运行
func SafeGo(fn func(), cb ...RecoveryCallback) {
go func() {
defer Recover(cb...)
fn()
}()
}
// SafeGoWithContext 带 Recover 的 goroutine 运行
func SafeGoWithContext(ctx context.Context, fn func(ctx context.Context), cb ...RecoveryCallback) {
go func() {
defer Recover(cb...)
fn(ctx)
}()
}
// SafeGoCommonFunc 带 Recover 的 goroutine 运行
func SafeGoCommonFunc(args interface{}, fn func(args interface{}), cb ...RecoveryCallback) {
go func() {
defer Recover(cb...)
fn(args)
}()
}
// WaitSignal 等待系统信号
// 默认捕获退出类信息
func WaitSignal(sig ...os.Signal) os.Signal {
if len(sig) == 0 {
sig = []os.Signal{syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT}
}
ch := make(chan os.Signal, 1)
signal.Notify(ch, sig...)
return <-ch
}
// FastRand 随机数
//
//go:linkname FastRand runtime.fastrand
func FastRand() uint32
// FastRandn 等同于 FastRand() % n, 但更快
// See https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
//
//go:linkname FastRandn runtime.fastrandn
func FastRandn(n uint32) uint32
// CPUTicks CPU 时钟周期, 更高精度 (云服务器做伪随机数种子时慎用)
//
//go:linkname CPUTicks runtime.cputicks
func CPUTicks() int64
// NanoTime 返回当前时间 (以纳秒为单位)
//
//go:linkname NanoTime runtime.nanotime
func NanoTime() int64