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