调用者如何从子 goroutine 的恐慌中恢复
How does a caller function to recover from child goroutine's panics
我曾经认为 goroutine 中的恐慌会杀死程序,如果它的调用者在恐慌之前完成(延迟恢复没有帮助,因为那时还没有恐慌发生),
直到我尝试了以下代码:
func fun1() {
fmt.Println("fun1 started")
defer func() {
if err := recover(); err != nil {
fmt.Println("recover in func1")
}
}()
go fun2()
time.Sleep(10 * time.Second) // wait for the boom!
fmt.Println("fun1 ended")
}
func fun2() {
fmt.Println("fun2 started")
time.Sleep(5 * time.Second)
panic("fun2 booom!")
fmt.Println("fun2 ended")
}
我发现无论调用者函数是否完成,如果它启动的goroutines panic,调用者的延迟恢复机制将无济于事。整个程序还是死了
那么,为什么?理论上调用函数仍然是运行。当恐慌发生时,调用者的延迟函数应该工作(包括恢复)。
While executing a function F, an explicit call to panic or a run-time panic terminates the execution of F. Any functions deferred by F are then executed as usual. Next, any deferred functions run by F's caller are run, and so on up to any deferred by the top-level function in the executing goroutine. At that point, the program is terminated and the error condition is reported, including the value of the argument to panic. This termination sequence is called panicking.
因为 fun2
是在 goroutine 中执行的顶层函数并且 fun2
不会从恐慌中恢复,当 fun2
恐慌时程序终止。
fun1
中的延迟调用不会在 goroutine 执行 fun2
panic 时被调用。
一个 goroutine 无法从另一个 goroutine 的 panic 中恢复。
您可以在 fun2() 中使用 runtime.Goexit() 而不是在 fun1() 中恢复,这将
Goexit terminates the goroutine that calls it. No other goroutine is
affected.
类似
func fun2() {
defer func() {
if err := recover(); err != nil {
fmt.Println("Do some cleanup and teardown")
runtime.Goexit() //Here
}
}
...
}
我曾经认为 goroutine 中的恐慌会杀死程序,如果它的调用者在恐慌之前完成(延迟恢复没有帮助,因为那时还没有恐慌发生),
直到我尝试了以下代码:
func fun1() {
fmt.Println("fun1 started")
defer func() {
if err := recover(); err != nil {
fmt.Println("recover in func1")
}
}()
go fun2()
time.Sleep(10 * time.Second) // wait for the boom!
fmt.Println("fun1 ended")
}
func fun2() {
fmt.Println("fun2 started")
time.Sleep(5 * time.Second)
panic("fun2 booom!")
fmt.Println("fun2 ended")
}
我发现无论调用者函数是否完成,如果它启动的goroutines panic,调用者的延迟恢复机制将无济于事。整个程序还是死了
那么,为什么?理论上调用函数仍然是运行。当恐慌发生时,调用者的延迟函数应该工作(包括恢复)。
While executing a function F, an explicit call to panic or a run-time panic terminates the execution of F. Any functions deferred by F are then executed as usual. Next, any deferred functions run by F's caller are run, and so on up to any deferred by the top-level function in the executing goroutine. At that point, the program is terminated and the error condition is reported, including the value of the argument to panic. This termination sequence is called panicking.
因为 fun2
是在 goroutine 中执行的顶层函数并且 fun2
不会从恐慌中恢复,当 fun2
恐慌时程序终止。
fun1
中的延迟调用不会在 goroutine 执行 fun2
panic 时被调用。
一个 goroutine 无法从另一个 goroutine 的 panic 中恢复。
您可以在 fun2() 中使用 runtime.Goexit() 而不是在 fun1() 中恢复,这将
Goexit terminates the goroutine that calls it. No other goroutine is affected.
类似
func fun2() {
defer func() {
if err := recover(); err != nil {
fmt.Println("Do some cleanup and teardown")
runtime.Goexit() //Here
}
}
...
}