common_utils.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. package utils
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io/ioutil"
  6. "os"
  7. "path/filepath"
  8. "reflect"
  9. "runtime"
  10. "strings"
  11. "time"
  12. )
  13. // 获取当前执行目录
  14. func GetCurrentDir() (string, error) {
  15. dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
  16. if err != nil {
  17. return "", err
  18. }
  19. return strings.Replace(dir, "\\", "/", -1), nil
  20. }
  21. // 检查对象是否包含在指定集合内
  22. func Contains(set interface{}, obj interface{}) bool {
  23. targetValue := reflect.ValueOf(set)
  24. switch reflect.TypeOf(set).Kind() {
  25. case reflect.Slice, reflect.Array:
  26. for i := 0; i < targetValue.Len(); i++ {
  27. if targetValue.Index(i).Interface() == obj {
  28. return true
  29. }
  30. }
  31. case reflect.Map:
  32. if targetValue.MapIndex(reflect.ValueOf(obj)).IsValid() {
  33. return true
  34. }
  35. }
  36. return false
  37. }
  38. // 获取Unix时间戳
  39. func GetUTCTicks(datetime time.Time) int64 {
  40. return datetime.UnixNano() / int64(time.Millisecond)
  41. }
  42. var (
  43. dunno = []byte("???")
  44. centerDot = []byte("·")
  45. dot = []byte(".")
  46. slash = []byte("/")
  47. )
  48. // 获取调用堆栈信息
  49. func GetStack(skip int) []byte {
  50. buf := new(bytes.Buffer) // the returned data
  51. // As we loop, we open files and read them. These variables record the currently
  52. // loaded file.
  53. var lines [][]byte
  54. var lastFile string
  55. for i := skip; ; i++ { // Skip the expected number of frames
  56. pc, file, line, ok := runtime.Caller(i)
  57. if !ok {
  58. break
  59. }
  60. // Print this much at least. If we can't find the source, it won't show.
  61. _, _ = fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
  62. if file != lastFile {
  63. data, err := ioutil.ReadFile(file)
  64. if err != nil {
  65. continue
  66. }
  67. lines = bytes.Split(data, []byte{'\n'})
  68. lastFile = file
  69. }
  70. _, _ = fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line))
  71. }
  72. return buf.Bytes()
  73. }
  74. // source returns a space-trimmed slice of the n'th line.
  75. func source(lines [][]byte, n int) []byte {
  76. n-- // in stack trace, lines are 1-indexed but our array is 0-indexed
  77. if n < 0 || n >= len(lines) {
  78. return dunno
  79. }
  80. return bytes.TrimSpace(lines[n])
  81. }
  82. // function returns, if possible, the name of the function containing the PC.
  83. func function(pc uintptr) []byte {
  84. fn := runtime.FuncForPC(pc)
  85. if fn == nil {
  86. return dunno
  87. }
  88. name := []byte(fn.Name())
  89. // The name includes the path name to the package, which is unnecessary
  90. // since the file name is already included. Plus, it has center dots.
  91. // That is, we see
  92. // runtime/debug.*T·ptrmethod
  93. // and want
  94. // *T.ptrmethod
  95. // Also the package path might contains dot (e.g. code.google.com/...),
  96. // so first eliminate the path prefix
  97. if lastslash := bytes.LastIndex(name, slash); lastslash >= 0 {
  98. name = name[lastslash+1:]
  99. }
  100. if period := bytes.Index(name, dot); period >= 0 {
  101. name = name[period+1:]
  102. }
  103. name = bytes.Replace(name, centerDot, dot, -1)
  104. return name
  105. }