作者热门文章
- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
如何优雅地处理 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/
我是一名优秀的程序员,十分优秀!