1. 程式人生 > >golang 學習筆記 runtime.Caller

golang 學習筆記 runtime.Caller

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是怎麼設計的,不過應該是的有他們的道理吧。