gpt4 book ai didi

go - 从导入的包中跟踪 go routine?

转载 作者:IT王子 更新时间:2023-10-29 02:13:26 28 4
gpt4 key购买 nike

如何获取最后一个(理想情况下)go 例程(该应用程序有多个 go 例程)的堆栈跟踪,该例程发生 panic 并恢复并仅记录了一条不多的描述性错误消息?不知道哪个套路恢复了。另外,请记住我不会更改任何导入包的代码。这种 panic 发生在一些创建多个 go 例程的导入包中,因此我需要一种方法来获取最后恢复的例程的堆栈跟踪,以便找到 panic 的位置。

最佳答案

简短的回答是:不可能但也有异常(exception)

Golang 有一些堆栈控制方法和类型。

您可以使用 runtime/debug/SetTraceback 控制堆栈级别

func SetTraceback(level string)

SetTraceback sets the amount of detail printed by the runtime inthe traceback it prints before exiting due to an unrecovered panic or an internal runtime error. The level argument takes the same values as the GOTRACEBACK environment variable. For example, SetTraceback("all") ensure that the program prints all goroutines when it crashes.
See the package runtime documentation for details. If SetTraceback is called with a level lower than that of the environment variable, the call is ignored.

您还可以使用 runtime/debug/Stack 打印堆栈跟踪

func Stack() []byte

Stack returns a formatted stack trace of the goroutine that calls it. It calls runtime.Stack with a large enough buffer to capture the entire trace.

您还需要了解内置函数 recover 的工作原理。

The recover built-in function allows a program to manage behavior of a panicking goroutine. Executing a call to recover inside a deferred function (but not any function called by it) stops the panicking sequence by restoring normal execution and retrieves the error value passed to the call of panic. If recover is called outside the deferred function it will not stop a panicking sequence. In this case, or when the goroutine is not panicking, or if the argument supplied to panic was nil, recover returns nil. Thus the return value from recover reports whether the goroutine is panicking.

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)
}

如果包调用恢复

如果代码正在从 panic 中恢复,您需要使用调试器或删除 recover 以了解发生了什么,如下例所示,该示例表明已恢复的 panic 无法“恢复” "再次。

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 调试或者临时编辑包以记录完整的消息(一旦理解,您可以恢复更改)。

此外,如果您发现问题,请告知软件包作者,以便进行修复。

关于go - 从导入的包中跟踪 go routine?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39229698/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com