runtime.Caller 学习笔记
今天阅读log的源码的时候发现他会去调用runtime.Caller
获取文件名称跟行数好奇心就来了,java或者其他语言的开发中log打印文件名称跟行数是一种很正常的事,具体怎么实现的一直没有研究过。今天就研究下golang中是怎么实现的
func Caller(skip int) (pc uintptr, file string, line int, ok bool)
这是函数详情,更深入的详情你可以自己查询go的源码
func main() {
call()
}
func call() {
var calldepth = 1;
fmt.Println(runtime.Caller(calldepth))
}
写了一个很简单的测试函数开始学习。一开始不是太懂他的参数的skip是什么意思,多看了下log的源码发现这个的意思是层级的意思。经过多次测试发现层级从0开始到3的时候结束。
- 17356603 /Users/mac-mini/go/src/demo/3/demo2.go 14 true
- 17356511 /Users/mac-mini/go/src/demo/3/demo2.go 9 true
- 16939329 /usr/local/go/src/runtime/proc.go 198 true
- 17095168 /usr/local/go/src/runtime/asm_amd64.s 2361 true
结果一目了然,层次为0的时候返回我们调用runtime.Caller
的地方.为1的时候就是我们调用call函数的地方。 2跟3已经是go源码的调用了应该是用不到。
本来写完了都已经发布了,后来阅读了下runtime.Caller
的源码发现这货底层是能获取到调用函数名称的,可是他不返回。
_, frame, _ := stackExpander.next(callers, true)
pc = frame.PC
file = frame.File
line = frame.Line
这个是Caller源码的最后几行,他这里获取了一个frame从中取到了pc,file,line。当我翻阅Frame的struct后发现有个string类型名称为Function属性,打开下断点发现值是真的有正确。emmm具体的不知道google是怎么设计的,不过应该是的有他们的道理吧。