简短的回答是:不可能,但有例外。
Golang 有一些堆栈控制方法和类型。
您可以使用runtime/debug/SetTraceback控制堆栈级别
func SetTraceback(level string)
SetTraceback 设置运行时打印的详细信息量
在回溯中它在退出之前打印,因为
未恢复的恐慌或内部运行时错误。
level 参数采用与 GOTRACEBACK 相同的值
环境变量。例如, SetTraceback("all") 确保
程序在崩溃时会打印所有的 goroutine。
有关详细信息,请参阅包运行时文档。如果
SetTraceback 的调用级别低于
环境变量,调用被忽略。
您也可以使用runtime/debug/Stack 打印堆栈跟踪
func Stack() []byte
Stack 返回调用它的 goroutine 的格式化堆栈跟踪。它使用足够大的缓冲区调用 runtime.Stack 来捕获整个跟踪。
您还需要了解内置函数recover 的工作原理。
recover 内置函数允许程序管理
恐慌的 goroutine。在 deferred 中执行调用以恢复
函数(但不是它调用的任何函数)停止恐慌序列
通过恢复正常执行并检索传递给
恐慌的呼唤。如果在延迟函数之外调用recover,它将
不要停止恐慌的序列。在这种情况下,或者当 goroutine 不是
恐慌,或者如果提供给恐慌的参数为零,恢复返回
零。因此,recover 的返回值报告了 goroutine 是否是
惊慌失措。
func recover() interface{}
工作示例
这个例子假设包没有调用recover(在另一部分详细说明)。
Golang Playground Link
package main
import (
"log"
"errors"
"runtime/debug"
"time"
)
func f2() {
panic(errors.New("oops")) // line 11
}
func f1() {
f2() // line 15
}
func main() {
defer func() {
if e := recover(); e != nil {
log.Printf("%s: %s", e, debug.Stack()) // line 20
}
}()
go f1() // line 25
time.Sleep(time.Second * 1)
}
如果包调用恢复
如果代码正在从恐慌中恢复,您需要使用调试器或删除 recover 以了解发生了什么,如下例所示,该示例表明已恢复的恐慌无法再次“恢复”。
Golang Playground Link
package main
import (
"log"
"errors"
"runtime/debug"
"time"
)
func f2() {
panic(errors.New("oops")) // line 11
}
func f1() {
defer func() {
if e := recover(); e != nil {
log.Printf("internal %s: %s", e, debug.Stack()) // line 20
}
}()
f2() // line 15
}
func main() {
defer func() {
if e := recover(); e != nil {
log.Printf("external %s: %s", e, debug.Stack()) // line 20
} else {
log.Println("Nothing to print")
}
}()
go f1() // line 25
time.Sleep(time.Second * 1)
}
少两害
使用Delve 调试或临时编辑包,以便记录完整消息(一旦了解,您可以恢复更改)。
此外,如果您发现问题,请告知包作者以便修复。