【Go】获取go的函数调用栈帧信息-runtime.Callers函数

搞了大半晚上,终于搞清楚了go的函数调用栈以及打印函数调用栈的相关函数,先简单记录一下结论

go的函数调用栈相关函数

func Callers(skip int, pc []uintptr) int

  • 该函数会将你这条goroutine函数调用链上的程序计数器pc返回到切片pc中(就是函数第二个参数)
  • 如果有协程,则这条链是从go关键字后面的函数开始到调用runtime.Callers所在的函数为止的
  • skip参数表示想要跳过的堆栈帧数,0表示Callers函数本身的栈帧,1表示调用Callers函数的栈帧
  • Callers返回值是这条函数调用链上的函数栈帧数
  • 搭配runtime.CallersFrames函数使用(见下面例子),返回一个runtime.Frame类型的结构体迭代器,遍历迭代器frame,可以得到当前函数的调用者的函数名(frame.Function)、调用者调用当前函数的代码所处行号(frame.Line)、调用者函数起始地址(frame.Entry)、调用者函数所在文件(frame.File)
  • 注意上一条!!!是打印当前函数的调用者的!!!!!!!!!!
package main

import (
	"fmt"
	"runtime"
	"time"
)

func A() {
	B()
}

func B() {
	pc := make([]uintptr, 100)
	n := runtime.Callers(0, pc)
	frames := runtime.CallersFrames(pc[:n])
	for i := 0; true; i++ {
		frame, more := frames.Next()
		fmt.Printf("file: %s, line: %d, function: %s, Address: %v\n",
			frame.File, frame.Line, frame.Function, frame.Entry)
		if !more {
			break
		}
	}
}

func main() {
	fmt.Printf("Callers address: %d\n", runtime.Callers)
	fmt.Printf("A address: %d\n", A)
	fmt.Printf("B address: %d\n", B)
	go A()
	time.Sleep(1 * time.Second)	// 这行要有
}

// 输出:
// Callers address: 1871424                                                                              
// A address: 2424160                                                                                    
// B address: 2424224                                                                                                                                                                                
// file: D:/Go/src/runtime/extern.go, line: 247, function: runtime.Callers, Address: 2424224             
// file: D:/Go_WorkSpace/test.go, line: 15, function: main.B, Address: 2424224
// file: D:/Go_WorkSpace/test.go, line: 10, function: main.A, Address: 2424160
// file: D:/Go/src/runtime/asm_amd64.s, line: 1594, function: runtime.goexit, Address: 2221344    

对比一下就可以发现,file: D:/Go_WorkSpace/test.go, line: 15, function: main.B, Address: 6487328 这个输出打印的是调用Callers函数的调用者的信息,同理file: D:/Go_WorkSpace/test.go, line: 10, function: main.A, Address: 6487264 打印的是调用函数B的调用者的信息


函数调用栈好文及资料

其他关于函数调用栈和栈帧的详细内容之后有空再记录吧,先记录一下相关资料

函数调用栈好文
函数调用栈资料
资料1
资料2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值