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  }