github.com/fufuok/utils@v1.0.10/runtime.go (about) 1 package utils 2 3 import ( 4 "context" 5 "log" 6 "os" 7 "os/signal" 8 "path/filepath" 9 "runtime" 10 "syscall" 11 _ "unsafe" 12 ) 13 14 const ( 15 // PtrSize 4 on 32-bit systems, 8 on 64-bit. 16 PtrSize = 4 << (^uintptr(0) >> 63) 17 ) 18 19 var StackTraceBufferSize = 4 << 10 20 21 // RecoveryCallback 自定义恢复信息回调 22 type RecoveryCallback func(err interface{}, trace []byte) 23 24 // CallPath 运行时路径, 编译目录 25 // 假如: mklink E:\tmp\linkapp.exe D:\Fufu\Test\abc\app.exe 26 // 执行: E:\tmp\linkapp.exe 27 // CallPath: E:\Go\src\github.com\fufuok\utils\tmp\osext 28 func CallPath() string { 29 _, filename, _, ok := runtime.Caller(1) 30 if ok { 31 return filepath.Clean(filepath.Dir(filename)) 32 } 33 34 return RunPath() 35 } 36 37 // RunPath 实际程序所在目录 38 // RunPath: E:\tmp 39 func RunPath() string { 40 dir, err := filepath.Abs(filepath.Dir(os.Args[0])) 41 if err != nil { 42 // 调用时工作目录 43 dir, _ = os.Getwd() 44 return dir 45 } 46 47 return dir 48 } 49 50 // Executable 当前执行程序绝对路径 51 // true 时返回解析符号链接后的绝对路径 52 // Excutable: E:\tmp\linkapp.exe 53 // Excutable(true): D:\Fufu\Test\abc\app.exe 54 func Executable(evalSymlinks ...bool) string { 55 exe, _ := os.Executable() 56 if len(evalSymlinks) > 0 && evalSymlinks[0] { 57 exe, _ = filepath.EvalSymlinks(exe) 58 } 59 60 return filepath.Clean(exe) 61 } 62 63 // ExecutableDir 当前执行程序所在目录 64 // true 时返回解析符号链接后的目录 65 // ExcutableDir: E:\tmp 66 // ExcutableDir(true): D:\Fufu\Test\abc 67 func ExecutableDir(evalSymlinks ...bool) string { 68 return filepath.Dir(Executable(evalSymlinks...)) 69 } 70 71 // Recover 从 panic 中恢复并记录堆栈信息 72 func Recover(cb ...RecoveryCallback) { 73 if err := recover(); err != nil { 74 buf := make([]byte, StackTraceBufferSize) 75 buf = buf[:runtime.Stack(buf, false)] 76 if len(cb) > 0 && cb[0] != nil { 77 cb[0](err, buf) 78 return 79 } 80 log.Printf("Recovery: %v\n--- Traceback:\n%v\n", err, B2S(buf)) 81 } 82 } 83 84 // SafeGo 带 Recover 的 goroutine 运行 85 func SafeGo(fn func(), cb ...RecoveryCallback) { 86 go func() { 87 defer Recover(cb...) 88 fn() 89 }() 90 } 91 92 // SafeGoWithContext 带 Recover 的 goroutine 运行 93 func SafeGoWithContext(ctx context.Context, fn func(ctx context.Context), cb ...RecoveryCallback) { 94 go func() { 95 defer Recover(cb...) 96 fn(ctx) 97 }() 98 } 99 100 // SafeGoCommonFunc 带 Recover 的 goroutine 运行 101 func SafeGoCommonFunc(args interface{}, fn func(args interface{}), cb ...RecoveryCallback) { 102 go func() { 103 defer Recover(cb...) 104 fn(args) 105 }() 106 } 107 108 // WaitSignal 等待系统信号 109 // 默认捕获退出类信息 110 func WaitSignal(sig ...os.Signal) os.Signal { 111 if len(sig) == 0 { 112 sig = []os.Signal{syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT} 113 } 114 ch := make(chan os.Signal, 1) 115 signal.Notify(ch, sig...) 116 return <-ch 117 } 118 119 // FastRand 随机数 120 // 121 //go:linkname FastRand runtime.fastrand 122 func FastRand() uint32 123 124 // FastRandn 等同于 FastRand() % n, 但更快 125 // See https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ 126 // 127 //go:linkname FastRandn runtime.fastrandn 128 func FastRandn(n uint32) uint32 129 130 // CPUTicks CPU 时钟周期, 更高精度 (云服务器做伪随机数种子时慎用) 131 // 132 //go:linkname CPUTicks runtime.cputicks 133 func CPUTicks() int64 134 135 // NanoTime 返回当前时间 (以纳秒为单位) 136 // 137 //go:linkname NanoTime runtime.nanotime 138 func NanoTime() int64