函数的调用信息是程序中比较重要运行期信息, 在很多场合都会用到(比如调试或日志).
runtimeruntime.Callerruntime.Callersruntime.FuncForPC
这几个函数的文档链接:
本文主要讲述这几个函数的用法.
runtime.Caller
函数的签名如下:
runtime.Callergoroutinepcokfalse
skip0runtime.Caller
runtime.Callerruntime.Callersskip
下面是一个简单的例子, 打印函数调用的栈帧信息:
skip = 0main.main
skip = 1skip = 2runtime/proc.cruntime.mainruntime.goexit
整理之后可以知道, Go的普通程序的启动顺序如下:
runtime.goexitmain.mainruntime.goexitruntime.mainruntime.mainmain.main
runtime.Callers
函数的签名如下:
runtime.Callersruntime.Callers
runtime.Callerspcskipruntime.Callerspc
runtime.Callerspc
pcskipskip = 0runtime.Callers
runtime.Callersruntime.Callers
runtime.Callersruntime.Caller
runtime.Callersruntime.Caller
pc
42809624290608pcruntime.mainruntime.goexit
runtime.Caller4198456runtime.Callers4198635pc
runtime.Callers4305334runtime.Callers
pc
runtime.FuncForPC
函数的签名如下:
runtime.FuncForPCpcpcnil
runtime.Func.FileLinepcpc
runtime.Func.Entryruntime.Func.Name
runtime.FuncForPC
pc0runtime.Func.FileLineruntime.Callerruntime.Func.FileLinepc
CallerName
CallerNameCallerName
函数实现如下:
runtime.Callerskip + 1CallerName
CallerName
这样就可以方便的输出函数调用者的信息了.
Go语言中函数的类型
在Go语言中, 除了语言定义的普通函数调用外, 还有闭包函数/init函数/全局变量初始化等不同的函数调用类型.
PrintCallerName
观察输出结果, 可以发现以下几个规律:
main.initinitmain.init·1main.init·2main.func·001
main.init
initmain.init·1main.init·2
001002003
CallerName
CallerName
init
CallerNameinitinit
处理的思路:
init"init·d+$"initfunc"func·d+$"
CallerName
有以下的代码:
myInitinitmainmyInit
myInitmain.myInitmain.myInitmain.func·???main.myInit
callerNamemain.func·???main.funcgettext.Gettext
callerName
不同Go程序启动流程
基于函数调用者信息可以很容易的验证各种环境的程序启动流程.
caller
caller/main.go
分析输出数据我们可以发现, 测试代码和例子代码的启动流程和普通的程序流程都不太一样.
测试代码的启动流程:
runtime.goexitruntime.goexitruntime.maintesting.tRunnertesting.tRunnergo test
例子代码的启动流程:
runtime.goexitruntime.goexitruntime.mainruntime.maingo testmain.main_test/_testmain.gotesting.Main
main.mainmainmainmainmain.mainmain.main
2015.06.09补充: 更深入的可以看下这个文章 GO语解惑:从源码分析GO程序的入口
总结
runtimeruntime.Callerruntime.Callersruntime.FuncForPC
这几个函数不仅可以解决一些实际的工程问题(比如 gettext-go 中用于获取翻译的上下文信息), 而且非常适合用于调试和分析各种Go程序的运行时信息.