我创建了一个并发运行函数的示例,在该示例中,我执行了异常处理和恢复:
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中的恐慌。
更新
我试着遵循@Momer的建议,通过通道发送一个错误,并在主goroutine中处理它,而不是试图制造恐慌:
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发布于 2016-01-21 17:57:46
我把golang中的panic/recover看作是java或c++中的try/catch/final块。
有关更多详细信息,请访问Handling panics (from Golang spec)。
因此,您可以将异常传递给方法的调用者。下面是一个简单的代码,希望它能有所帮助
注意:在函数Foo()中,我使用recover()来捕获错误,然后重新引发恐慌,以便稍后在外部调用者中捕获它。
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-------------")
}发布于 2015-04-06 22:31:10
在您更新的问题中,一个线程通过从chanStr读取数据而被阻塞,而另一个线程通过向chanErr写入数据而被阻塞。改变写入顺序应该可以解决死锁问题。
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")
}
chanStr <- ""
chanErr <- err
}
}https://stackoverflow.com/questions/29457856
复制相似问题