如何获得恐慌的堆栈跟踪(并存储为变量)

hli*_*117 17 debugging go panic

众所周知,恐慌会产生一个堆栈跟踪到stdout(Playground链接):

panic: runtime error: index out of range
goroutine 1 [running]:
main.main()
    /tmp/sandbox579134920/main.go:9 +0x20
Run Code Online (Sandbox Code Playgroud)

当你从恐慌中恢复时,似乎recover()只返回error描述导致恐慌的原因(游乐场链接).

runtime error: index out of range
Run Code Online (Sandbox Code Playgroud)

我的问题是,是否可以存储写入stdout的堆栈跟踪?这提供了比字符串更好的调试信息,runtime error: index out of range因为它显示文件中引起恐慌的确切行.

hli*_*117 19

就像上面提到的@Volker一样,以及作为评论发布的内容,我们都可以使用该runtime/debug包。

package main

import (
    "fmt"
    "runtime/debug"
)

func main() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("stacktrace from panic: \n" + string(debug.Stack()))
        }
    }()

    var mySlice []int
    j := mySlice[0]

    fmt.Printf("Hello, playground %d", j)
}
Run Code Online (Sandbox Code Playgroud)

版画

stacktrace from panic: 
goroutine 1 [running]:
runtime/debug.Stack(0x1042ff18, 0x98b2, 0xf0ba0, 0x17d048)
    /usr/local/go/src/runtime/debug/stack.go:24 +0xc0
main.main.func1()
    /tmp/sandbox973508195/main.go:11 +0x60
panic(0xf0ba0, 0x17d048)
    /usr/local/go/src/runtime/panic.go:502 +0x2c0
main.main()
    /tmp/sandbox973508195/main.go:16 +0x60
Run Code Online (Sandbox Code Playgroud)

游乐场链接

  • 为了清楚起见(因为这种情况没有明确测试):当您在restore()内部时,函数debug.Stack()将返回PANIC的堆栈,而不仅仅是返回deferred函数的词法堆栈。 (3认同)

Him*_*shu 9

创建一个日志文件以将堆栈跟踪添加到 stdout 或 stderr 文件中。这将添加数据,包括文件中错误行的时间。

package main

import (
    "log"
    "os"
    "runtime/debug"
)

func main() {

    defer func() {
        if r := recover(); r != nil {
            log.Println(string(debug.Stack()))
        }
    }()

    //create your file with desired read/write permissions
    f, err := os.OpenFile("filename", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
    if err != nil {
        log.Println(err)
    }

    //set output of logs to f
    log.SetOutput(f)
    var mySlice []int
    j := mySlice[0]

    log.Println("Hello, playground %d", j)

    //defer to close when you're done with it, not because you think it's idiomatic!
    f.Close()
}
Run Code Online (Sandbox Code Playgroud)

Go Playground上的工作示例