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