比如下面这个例子,我们使用 Caller 方法,将文件名、行号、堆栈函数打印出来:
// 在 prog.go 文件,main 库中调用 call 方法func call(skip int) bool { //24 行pc,file,line,ok := runtime.Caller(skip) //25 行pcName := runtime.FuncForPC(pc).Name() //26 行fmt.Println(fmt.Sprintf("%v %s %d %s",pc,file,line,pcName)) //27 行return ok //28 行} //29 行
打印出的第一层堆栈函数的信息:
4821380 /tmp/sandbox064396492/prog.go 25 main.call
打印堆栈的时候就有这么一个逻辑:先去本地查找是否有这个源代码文件,如果有的话,获取堆栈所在的代码行数,将这个代码行数直接打印到控制台中。
// 打印具体的堆栈信息func stack(skip int) []byte {...// 循环从第 skip 层堆栈到最后一层for i := skip; ; i++ {pc, file, line, ok := runtime.Caller(i)// 获取堆栈函数所在源文件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()}
这样,打印出来的堆栈信息形如:
/Users/yejianfeng/Documents/gopath/pkg/mod/github.com/gin-gonic/[email protected]/context.go:165 (0x1385b5a)(*Context).Next: c.handlers[c.index](c)
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论