gpt4 book ai didi

go - 如何从 WaitGroup 调用的函数中捕获运行时错误?

转载 作者:IT王子 更新时间:2023-10-29 01:27:51 27 4
gpt4 key购买 nike

如何优雅地处理 WaitGroup 中的崩溃?

换句话说,在下面的代码片段中,如何捕获 goroutines 调用方法 do() 的 panics/crashes?

func do(){
str := "abc"
fmt.Print(str[3])
defer func() {
if err := recover(); err != nil {
fmt.Print(err)
}
}()
}

func main() {
var wg sync.WaitGroup

for i := 0; i < 1; i++ {
wg.Add(1)
go do()
defer func() {
wg.Done()
if err := recover(); err != nil {
fmt.Print(err)
}
}()
}
wg.Wait()
fmt.Println("This line should be printed after all those invocations fail.")
}

最佳答案

首先,注册一个要恢复的延迟函数应该是函数的第一行,因为你最后一次这样做,它甚至不会到达,因为 defer 之前的行/代码已经 panic ,因此延迟函数不会被注册,这将 recover panic 状态。

因此,将您的 do() 函数更改为:

func do() {
defer func() {
if err := recover(); err != nil {
fmt.Println("Restored:", err)
}
}()
str := "abc"
fmt.Print(str[3])
}

第二:仅此一项不会使您的代码正常工作,因为您在延迟函数中调用 wg.Defer(),该函数只会在 main() 完成后运行 -这绝不是因为您在 main() 中调用了 wg.Wait()。所以 wg.Wait() 等待 wg.Done() 调用,但是 wg.Done() 调用直到 wg.Wait() 返回。这是一个僵局。

您应该在延迟函数中从 do() 函数调用 wg.Done(),如下所示:

var wg sync.WaitGroup

func do() {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
wg.Done()
}()
str := "abc"
fmt.Print(str[3])
}

func main() {
for i := 0; i < 1; i++ {
wg.Add(1)
go do()
}
wg.Wait()
fmt.Println("This line should be printed after all those invocations fail.")
}

输出(在 Go Playground 上尝试):

Restored: runtime error: index out of range
This line should be printed after all those invocations fail.

这当然需要将 wg 变量移动到全局范围。另一种选择是将其作为参数传递给 do()。如果您决定采用这种方式,请注意您必须传递一个指向 WaitGroup 的指针。 , 否则只会传递一个副本(WaitGroup 是一个 struct 类型)并且在副本上调用 WaitGroup.Done() 不会生效在原件上。

WaitGroup 传递给 do():

func do(wg *sync.WaitGroup) {
defer func() {
if err := recover(); err != nil {
fmt.Println("Restored:", err)
}
wg.Done()
}()
str := "abc"
fmt.Print(str[3])
}

func main() {
var wg sync.WaitGroup
for i := 0; i < 1; i++ {
wg.Add(1)
go do(&wg)
}
wg.Wait()
fmt.Println("This line should be printed after all those invocations fail.")
}

输出是一样的。在 Go Playground 上试试这个变体.

关于go - 如何从 WaitGroup 调用的函数中捕获运行时错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34196188/

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