[golang]如何看懂調(diào)用堆棧

之前也有文章講過go調(diào)用堆棧的話題,但并沒有完全講清楚,這里補充里面缺漏的幾個點。

阻塞

goroutine 1 [select, 2 minutes]:

方括號里的select表示阻塞原因,具體定義見runtime.waitReason
后面的時間是阻塞時間。需要注意的是這只是一個大概時間,是在gc的過程中標記的,所以如果這個goroutine不需要gc,那么永遠也不會有值。

PC偏移

github.com/robfig/cron.(*Cron).run(0xc0000c44b0)
    cron.go:191 +0x28d

行號后面的16進制數(shù)是什么?pc偏移。是指函數(shù)入口(cron.(*Cron).run)到調(diào)用處(也就是行號指位置)的指令位置偏差。一般很少用到,除非下面這種特殊情況:

func main() {
    rand.Seed(time.Now().UnixNano())
    _, _, _ = foo(), foo(), foo()
}

func foo() int {
    if rand.NormFloat64() > 0 {
        panic("")
    }
    return 0
}

//main.main()
//  main.go:10 +0x7b 或 +0x80 或 +0x85

函數(shù)參數(shù)

函數(shù)參數(shù)是最復雜的部分,牽涉到go的很多底層實現(xiàn)。

輸入?yún)?shù),輸出參數(shù)

為什么經(jīng)常只有一個參數(shù)的函數(shù)堆棧里卻跟著兩個數(shù)呢?另一個是輸出。

func main() {
    rand.Seed(time.Now().UnixNano())
    r := rand.Int() //2e78e7b163438cc2
    fmt.Printf("%x\n", r)
    foo(r)
}

func foo(i int) (o int) {
    o = rand.Int() //36dd26e720cac1fe
    fmt.Printf("%x\n", o)
    defer panic("want to panic")
    return
}

//main.foo(2e78e7b163438cc2, 36dd26e720cac1fe)
//  main.go:21 +0xdd
結(jié)構(gòu)體展開

結(jié)構(gòu)體會被展開,然后比較短的字段會被打包成一個uint。

type S struct {
    a int
    b int
    c int
    d int
    a1 bool
    b1 byte
    c1 bool
    d1 byte
}

func main() {
    foo(S{})
}

func foo(s S) {
    panic("want to panic")
    noInline()
}

func noInline() {
    fmt.Sprint()
}

//main.foo(0x0, 0x0, 0x0, 0x0, 0x0)
//  main.go:67 +0x39

但是這種打包是依賴字段順序的。

type S struct {
    a int
    a1 bool
    b int
    b1 bool
    c int
    c1 bool
    d int
    d1 bool
}

func main() {
    foo(S{})
}

func foo(s S) {
    panic("want to panic")
    noInline()
}

func noInline() {
    fmt.Sprint()
}

//main.foo(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
//  main.go:67 +0x39
函數(shù)參數(shù)對照表

下面的表涵蓋了大部分情況

函數(shù)簽名 輸入 堆棧輸出 說明
foo(float64) 1 (0x3ff0000000000000)
foo(complex64) 1+3i (0x404000003f800000) 兩個32位浮點打包為一個64位數(shù)
foo(complex128) 1+3i (0x3ff0000000000000, 0x4008000000000000)
foo(string) "中文" (0x10adc82, 0x6) (指針,字節(jié)數(shù))
foo(interface{}) "" (0x108e520, 0x10bff30) (類型指針,值指針)
foo(interface{}) (*string)(nil) (0x108b8e0, 0x0) 值為nil,類型不為nil
foo(interface{}) nil (0x0, 0x0) 值,類型都為nil
foo([]byte) make([]byte,3,6) (0xc000070f82, 0x3, 0x6) (指針,len,cap)
foo(map[string]string) make(map[string]string) (0xc000070e48)
foo(chan struct{}) make(chan struct{}) (0xc00005e060)
foo([200]int) [200]int{} (0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...) 數(shù)組展開
foo(func()) nil (0x0)
foo(int16, uint16) 1,2 (0xc000020001) 兩個16位數(shù)打包為32位數(shù),僅低32位有效
foo(bool)bool false (0xc000070f00, 0xc00005c058) 前一個數(shù)為輸入,僅低8位有效,后一個數(shù)為輸出,未初始化
foo(struct {a,b int}) struct {a,b int}{} (0x0, 0x0) 結(jié)構(gòu)體展開
foo(struct {a int;b bool;c int;d bool;e byte}) struct {a int;b bool;c byte;d bool;e byte}{1,true,2,false,3} (0x1, 0x1, 0x2, 0x300) d,e合并,b不合并
foo(struct {a int;b bool;c string;d bool;e byte}) struct {a int;b bool;c string;d bool;e byte}{1,true,"a",false,3} (0x1, 0x1, 0x10adb18, 0x1, 0x300) d,e合并
foo(struct {a struct{a,b byte};b bool}) struct {a struct{a,b byte};b bool}{struct{a,b byte}{3,4},true} (0xc000010403) 內(nèi)嵌結(jié)構(gòu)體合并
foo(struct {a struct{a int;b byte};b bool}) struct {a struct{a int;b byte};b bool}{struct {a int;b byte}{5 , 7 },false} (0x5, 0xc000072f07, 0xc00005e000) 內(nèi)嵌結(jié)構(gòu)體不合并
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 一、Python簡介和環(huán)境搭建以及pip的安裝 4課時實驗課主要內(nèi)容 【Python簡介】: Python 是一個...
    _小老虎_閱讀 6,337評論 0 10
  • Lua 5.1 參考手冊 by Roberto Ierusalimschy, Luiz Henrique de F...
    蘇黎九歌閱讀 14,251評論 0 38
  • 第二部分 自動內(nèi)存管理機制 第二章 java內(nèi)存異常與內(nèi)存溢出異常 運行數(shù)據(jù)區(qū)域 程序計數(shù)器:當前線程所執(zhí)行的字節(jié)...
    小明oh閱讀 1,282評論 0 2
  • 這篇文章是我之前翻閱了不少的書籍以及從網(wǎng)絡上收集的一些資料的整理,因此不免有一些不準確的地方,同時不同JDK版本的...
    高廣超閱讀 16,051評論 3 83
  • 血在嘶吼, 盔甲在棄散, 我把尊嚴放入籃子 和死亡一起, 我曾用短刃刺穿暴怒, 曾流淚祈求苦難寬恕, 現(xiàn)在, 敵人...
    葡萄美酒閱讀 256評論 0 0

友情鏈接更多精彩內(nèi)容