123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- package utils
- import (
- "bytes"
- "fmt"
- "io/ioutil"
- "os"
- "path/filepath"
- "reflect"
- "runtime"
- "strings"
- "time"
- )
- // 获取当前执行目录
- func GetCurrentDir() (string, error) {
- dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
- if err != nil {
- return "", err
- }
- return strings.Replace(dir, "\\", "/", -1), nil
- }
- // 检查对象是否包含在指定集合内
- func Contains(set interface{}, obj interface{}) bool {
- targetValue := reflect.ValueOf(set)
- switch reflect.TypeOf(set).Kind() {
- case reflect.Slice, reflect.Array:
- for i := 0; i < targetValue.Len(); i++ {
- if targetValue.Index(i).Interface() == obj {
- return true
- }
- }
- case reflect.Map:
- if targetValue.MapIndex(reflect.ValueOf(obj)).IsValid() {
- return true
- }
- }
- return false
- }
- // 获取Unix时间戳
- func GetUTCTicks(datetime time.Time) int64 {
- return datetime.UnixNano() / int64(time.Millisecond)
- }
- var (
- dunno = []byte("???")
- centerDot = []byte("·")
- dot = []byte(".")
- slash = []byte("/")
- )
- // 获取调用堆栈信息
- func GetStack(skip int) []byte {
- buf := new(bytes.Buffer) // the returned data
- // As we loop, we open files and read them. These variables record the currently
- // loaded file.
- var lines [][]byte
- var lastFile string
- for i := skip; ; i++ { // Skip the expected number of frames
- pc, file, line, ok := runtime.Caller(i)
- if !ok {
- break
- }
- // Print this much at least. If we can't find the source, it won't show.
- _, _ = fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
- if file != lastFile {
- data, err := ioutil.ReadFile(file)
- if err != nil {
- continue
- }
- lines = bytes.Split(data, []byte{'\n'})
- lastFile = file
- }
- _, _ = fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line))
- }
- return buf.Bytes()
- }
- // source returns a space-trimmed slice of the n'th line.
- func source(lines [][]byte, n int) []byte {
- n-- // in stack trace, lines are 1-indexed but our array is 0-indexed
- if n < 0 || n >= len(lines) {
- return dunno
- }
- return bytes.TrimSpace(lines[n])
- }
- // function returns, if possible, the name of the function containing the PC.
- func function(pc uintptr) []byte {
- fn := runtime.FuncForPC(pc)
- if fn == nil {
- return dunno
- }
- name := []byte(fn.Name())
- // The name includes the path name to the package, which is unnecessary
- // since the file name is already included. Plus, it has center dots.
- // That is, we see
- // runtime/debug.*T·ptrmethod
- // and want
- // *T.ptrmethod
- // Also the package path might contains dot (e.g. code.google.com/...),
- // so first eliminate the path prefix
- if lastslash := bytes.LastIndex(name, slash); lastslash >= 0 {
- name = name[lastslash+1:]
- }
- if period := bytes.Index(name, dot); period >= 0 {
- name = name[period+1:]
- }
- name = bytes.Replace(name, centerDot, dot, -1)
- return name
- }
|