有时候在调用一个Go函数的过程中,我们需要知道是谁调用了这个函数,比如打印日志信息。例如,在下面的函数中,我们要在日志中打印调用者的名字。funcFoo(){fmt.Println("Whoiscallingme?")bar()}funcBar(){fmt.Println("Whoiscallingme?")}首先打印函数本身的名称最简单的方法很难编码。因为在编译之前,打印的时候我们必须知道在哪个函数,但是更好的办法是写一个通用的函数,比如下面这个例子:packagemainimport("fmt""runtime")funcmain(){Foo()}funcFoo(){fmt.Printf("我是%s,谁在给我打电话?\n",printMyName())Bar()}funcBar(){fmt.Printf("我是%s,谁在给我打电话?\n",printMyName())}funcprintMyName()string{pc,_,_,_:=runtime.Caller(1)returnruntime.FuncForPC(pc).Name()}输出结果:我是main.Foo,whoCallme?我是main.Bar,谁在叫我?您可以看到,当函数被调用时,printMyName会打印函数本身的名称。注意这里Caller的参数是1,因为我们把业务代码封装成了一个函数。首先打印函数调用者的名字修改上面的代码,增加一个新的printCallerName函数,可以打印调用者的名字。funcmain(){Foo()}funcFoo(){fmt.Printf("我是%s,%s正在打电话给我!\n",printMyName(),printCallerName())Bar()}funcBar(){fmt.Printf("我是%s,%s又给我打电话了!\n",printMyName(),printCallerName())}funcprintMyName()string{pc,_,_,_:=runtime.Caller(1)returnruntime.FuncForPC(pc).Name()}funcprintCallerName()string{pc,_,_,_:=runtime.Caller(2)returnruntime.FuncForPC(pc).Name()}相关函数介绍可以使用runtime.Caller,runtime.Callers和runtime.FuncForPC等函数更详细地跟踪函数的调用堆栈。1.funcCaller(skipint)(pcuintptr,filestring,lineint,okbool)Caller可以返回程序计数器、文件信息、函数调用栈某一层的行号。0代表当前函数,也就是调用runtime.Caller的函数。1代表上一层的调用者,以此类推。2.funcCallers(skipint,pc[]uintptr)intCallers用于返回调用站的程序计数器,放在一个uintptr中。0代表Callers本身,与上面的Caller参数不同,这是历史原因造成的。1对应上面的0。比如在上例中添加一个trace函数,由函数Bar调用。...funcBar(){fmt.Printf("我是%s,%s又给我打电话了!\n",printMyName(),printCallerName())trace()}functrace(){pc:=make([]uintptr,10)//atleast1entryneededn:=runtime.Callers(0,pc)fori:=0;i
