gpt4 book ai didi

go - 将恢复传递给上层 goroutine golang

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

我创建了一个示例,在该示例中我同时运行函数,在其中我会 panic 并恢复:

package main

import "fmt"

func main() {
// "main" recovery
defer func() {
if r := recover(); r != nil {
fmt.Println("main goroutine paniced:", r)
}
}()

// running function concurrently inside which I panic
chanStr := make(chan string)
go func() {
// this "internal" goroutin recovery
defer func() {
if r := recover(); r != nil {
fmt.Println("internal goroutine paniced:", r)
}
chanStr <- "hello world"
}()
// panicking and wanting recovery not only in "internal" recovery but in "main" recovery as well
panic("NOT main goroutine")
}()
// waiting for chan with "internal" goroutine panicking and recovery
str := <-chanStr
fmt.Println(str)

// panic("main")
}

它给出输出:

internal goroutine panicked: NOT main goroutine
hello world

是否可以更改我的代码以将传递从“内部”恢复为“主要”?换句话说,我希望它写到控制台:

internal goroutine paniced: NOT main goroutine
main goroutine paniced: main
hello world

我试图通过完全删除“内部”恢复功能来实现这一点,但在这种情况下,“主要”恢复不会恢复“内部”goroutine 内的 panic 。

Playground

更新

我尝试遵循@Momer 的建议并通过 channel 发送错误并在主 goroutine 中处理它,而不是试图引发 panic :

package main

import (
"errors"
"fmt"
)

func main() {
// "main" recovery
defer func() {
if r := recover(); r != nil {
fmt.Println("main goroutine paniced:", r)
}
}()

// running func concarantly inside which I panic
chanStr := make(chan string)
chanErr := make(chan error)
var err error
go func() {
// this "internal" goroutin recovery
defer func() {
if r := recover(); r != nil {
fmt.Println("internal goroutine paniced:", r)
switch t := r.(type) {
case string:
fmt.Println("err is string")
err = errors.New(t)
case error:
fmt.Println("err is error")
err = t
default:
fmt.Println("err is unknown")
err = errors.New("Unknown error")
}

chanErr <- err
chanStr <- ""
}
}()
// panicing and wanting recovery not only in "internal" recovery but in "main" recovery as well
panic("NOT main goroutine")
chanStr <- "hello world"
chanErr <- nil

}()
// waiting for chan with "internal" goroutin panicing and recovery
str := <-chanStr
err = <-chanErr
fmt.Println(str)
fmt.Println(err)

// panic("main")
}

报错

all goroutines are asleep - deadlock

完整输出:

go run /goPath/parentRecoverty2.go
internal goroutine paniced: NOT main goroutine
err is string
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()
/goPath/parentRecoverty2.go:48 +0x1d4

goroutine 5 [chan send]:
main.func·002()
/goPath/parentRecoverty2.go:37 +0x407
main.func·003()
/goPath/parentRecoverty2.go:42 +0x130
created by main.main
/goPath/parentRecoverty2.go:46 +0x190
exit status 2

Update playground

最佳答案

我将 golang 中的 panic/recover 视为 java 或 c++ 中的 try/catch/final block 。

更多详情,您可以访问Handling panics (from Golang spec) .

因此您可以将 panic 传递给方法的调用者。下面是一个简单的代码,希望对您有所帮助

注意:在函数 Foo() 中,我使用 recover() 来捕捉出错的地方,然后重新 panic 以便稍后在外部调用者中捕捉它。

package main

import (
"fmt"
"time"
)

func Foo() {
defer func() {
if x := recover(); x != nil {
fmt.Printf("Runtime panic: %v \n", x)
panic("Ah oh ... Panic in defer")
}
}()
panic("Panic in Foo() !")
}

func Game() {
defer func(){
fmt.Println("Clean up in Game()")
}()

defer func() {
if x := recover(); x != nil {
fmt.Println("Catch recover panic !!! In Game()")
}
}()
Foo()

}

func main() {

defer func() {
fmt.Println("Program Quit ... ")
}()

fmt.Println("-----------Split-------------")
go Game()
time.Sleep(1 * time.Millisecond)
fmt.Println("-----------Split-------------")
}

关于go - 将恢复传递给上层 goroutine golang,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29457856/

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