Golang 里 goroutine a 调用 goroutine b, b 里面发生了 panic,能知道是谁调用了 a 导致这次请求的吗?

2023-05-15 13:23:54 +08:00
 lightjiao

比如如下代码,开发时如何知道这个 panic 是由于 main 函数调用触发的

func main() {
    go TestGoException()
    time.Sleep(1000)
}

func TestGoException() {
    go TestGoException2()
}

func TestGoException2() {
    panic("this is a panic")
}
1842 次点击
所在节点    Go 编程语言
14 条回复
aapeli
2023-05-15 13:32:08 +08:00
time.Sleep(1000) 这个值太小了(1000 纳秒), 改成 time.Sleep(time.Second * 1) 试试, panic 后堆栈会打印出来


```xxx
panic: this is a panic

goroutine 6 [running]:
main.TestGoException2()
/Users/aapeli/main.go:15 +0x45
created by main.TestGoException
/Users/aapeli/main.go:10 +0x25
exit status 2
```
aapeli
2023-05-15 13:33:01 +08:00
通过堆栈信息可以获取到最近一次 panic 产生的位置.
GopherDaily
2023-05-15 13:33:05 +08:00
- 记忆中没有
- 间接的方法是用 context 传递
- 这是个伪需求
GopherDaily
2023-05-15 13:35:01 +08:00
AnroZ
2023-05-15 13:37:37 +08:00
如果在 TestGoException2 函数内可以 recover 的话,是可以通过获取 runtime.Stack 获取调用堆栈信息。比如:
```
func TestGoException2() {
defer func() {
if info := recover(); info != nil {
fmt.Println(info)

buff := make([]byte, 1024)
runtime.Stack(buff, false)

fmt.Println(string(buff))
}
}()

panic("this is a panic")
}
```
lightjiao
2023-05-15 13:59:14 +08:00
@aapeli
@AnroZ
我分别尝试了二位的方法,并不能打印出完整的 stack ,无法知道最开始是 main 调用触发的,还是其他函数触发的
lightjiao
2023-05-15 14:00:12 +08:00
@GopherDaily
开发期间追踪异步调用链排查问题是最基础的需求
Context 我没试过,对这块不太熟
aapeli
2023-05-15 14:11:28 +08:00
```xxx
panic: this is a panic

goroutine 6 [running]:
main.TestGoException2()
/Users/aapeli/main.go:15 +0x45 # painic 的位置
created by main.TestGoException
/Users/aapeli/main.go:10 +0x25. # 这里有告诉你是谁调用的 TestGoException2
exit status 2
```
lightjiao
2023-05-15 14:12:58 +08:00
@aapeli 我期望的是谁调用了 TestGoException ,需要一条完整的异步调用链
docxs
2023-05-15 14:16:26 +08:00
g 的原始结构里有个 gopc 字段,是创建这个 g 的父 g 的 pc 位置,试试依次回溯
aapeli
2023-05-15 14:19:30 +08:00
要不试试 jaeger 之类的 opentracing 吧,成熟的链路追踪产品,有 UI 告诉你相关的调用链路

https://github.com/opentracing/opentracing-go
https://www.jaegertracing.io/
https://github.com/jaegertracing/jaeger
lightjiao
2023-05-15 14:21:59 +08:00
@aapeli 链路追踪产品是给分布式微服务用的,我这里显然不是这个场景,你可以看一下我的 append
hzzhzzdogee
2023-05-15 14:41:34 +08:00
f 应该没有办法
AnroZ
2023-05-15 18:28:39 +08:00
@lightjiao runtime.Stack(buff, true)倒是可以打印所有在运行的堆栈。
但在你这个例子中,因为调用 TestGoException 的 goroutine 其实也早已退出了,所以即使调用 runtime.Stack(buff, true)也是打印不出来的。
如果你想实现你想要的追溯,建议自己增加 log 记录或增加上下文信息

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/940100

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX