github.com/pubgo/xprocess@v0.1.11/xutil/frame.go (about) 1 package xutil 2 3 import ( 4 "reflect" 5 "runtime" 6 "strconv" 7 "strings" 8 9 "github.com/pubgo/xerror" 10 "github.com/pubgo/xprocess/xprocess_strings" 11 ) 12 13 type frame uintptr 14 15 func (f frame) pc() uintptr { return uintptr(f) - 1 } 16 17 // CallerStack 调用栈 18 func CallerStack(cd int, fns ...func(fn *runtime.Func, pc uintptr) string) string { 19 var pcs = make([]uintptr, 1) 20 if runtime.Callers(cd, pcs[:]) == 0 { 21 return "" 22 } 23 24 f := frame(pcs[0]) 25 fn := runtime.FuncForPC(f.pc()) 26 if fn == nil { 27 return "unknown type" 28 } 29 30 if len(fns) > 0 { 31 return fns[0](fn, f.pc()) 32 } 33 34 file, line := fn.FileLine(f.pc()) 35 return xprocess_strings.Append(file, ":", strconv.Itoa(line)) 36 } 37 38 // FuncStack 函数栈 39 func FuncStack(fn interface{}, fns ...func(fn *runtime.Func, pc uintptr) string) string { 40 xerror.Assert(fn == nil, "[fn] is nil") 41 42 var vfn = reflect.ValueOf(fn) 43 xerror.Assert(!vfn.IsValid() || vfn.Kind() != reflect.Func || vfn.IsNil(), "[fn] func is nil or type error") 44 45 var fnStack = runtime.FuncForPC(vfn.Pointer()) 46 if len(fns) > 0 { 47 fns[0](fnStack, vfn.Pointer()) 48 } 49 50 var file, line = fnStack.FileLine(vfn.Pointer()) 51 ma := strings.Split(fnStack.Name(), ".") 52 return xprocess_strings.Append(file, ":", strconv.Itoa(line), " ", ma[len(ma)-1]) 53 }