如何处理外部的恐慌

huangapple go评论76阅读模式
英文:

How to handle panic outside

问题

请看下面的代码片段。

package main

import "fmt"

func explode() {
	// 引发 panic。
	panic("WRONG")
}

func recovery() int {
	explode()
	defer func() {
		fmt.Println("尝试处理 panic")
		if err := recover(); err != nil {
			fmt.Println("修复")
			fmt.Println("错误", err)
		}
	}()
	fmt.Println("打印值")
	return 100

}

func main() {
	// 使用 recover 在 defer 函数中处理错误。
	fmt.Println(recovery())
}

如你所见,我在 explode 函数中引发了一个 panic,并希望在 recovery 函数中处理它。但是 panic 没有被捕获,我得到了运行时错误。

goroutine 1 [running]:
main.explode()
        D:/gocode/src/samples/panic1.go:7 +0x6b
main.recovery(0xc082002250)
        D:/gocode/src/samples/panic1.go:18 +0x26
main.main()
        D:/gocode/src/samples/panic1.go:27 +0x26

goroutine 2 [runnable]:
runtime.forcegchelper()
        c:/go/src/runtime/proc.go:90
runtime.goexit()
        c:/go/src/runtime/asm_amd64.s:2232 +0x1

goroutine 3 [runnable]:
runtime.bgsweep()
        c:/go/src/runtime/mgc0.go:82
runtime.goexit()
        c:/go/src/runtime/asm_amd64.s:2232 +0x1

goroutine 4 [runnable]:
runtime.runfinq()
        c:/go/src/runtime/malloc.go:712
runtime.goexit()
        c:/go/src/runtime/asm_amd64.s:2232 +0x1
exit status 2

如何在 recovery 函数中捕获 panic?

英文:

Look at the following code snippet.

package main

import "fmt"

func explode() {
	// Cause a panic.
	panic("WRONG")
}

func recovery() int {
	explode()
	defer func() {
		fmt.Println("Try to handle panic")
		if err := recover(); err != nil {
			fmt.Println("FIX")
			fmt.Println("ERR", err)
		}
	}()
	fmt.Println("Print value")
	return 100

}

func main() {
	// Handle errors in defer func with recover.
	fmt.Println(recovery())
}

As you can see code above, I fired a panic in the explode function and want to handle it in the recovery function. But the panic does not get caught, I've got runtime error

goroutine 1 [running]:
main.explode()
        D:/gocode/src/samples/panic1.go:7 +0x6b
main.recovery(0xc082002250)
        D:/gocode/src/samples/panic1.go:18 +0x26
main.main()
        D:/gocode/src/samples/panic1.go:27 +0x26

goroutine 2 [runnable]:
runtime.forcegchelper()
        c:/go/src/runtime/proc.go:90
runtime.goexit()
        c:/go/src/runtime/asm_amd64.s:2232 +0x1

goroutine 3 [runnable]:
runtime.bgsweep()
        c:/go/src/runtime/mgc0.go:82
runtime.goexit()
        c:/go/src/runtime/asm_amd64.s:2232 +0x1

goroutine 4 [runnable]:
runtime.runfinq()
        c:/go/src/runtime/malloc.go:712
runtime.goexit()
        c:/go/src/runtime/asm_amd64.s:2232 +0x1
exit status 2

How to catch the panic in the recory function?

答案1

得分: 6

如果你首先调用explode()函数,处理panic并尝试恢复的函数尚未注册(并且永远不会注册,因为你在explode()函数内部调用了panic),所以它不会被调用,显然它无法完成其工作。

你需要先调用defer,然后再调用explode()函数:

defer func() {
    // 在这里进行recover(),你的代码被省略了
}()
explode()

Go Playground上尝试一下。

英文:

If you call explode() first, the function that would handle the panic and try to recover is not yet registered (and never will be because you call panic inside explode()), so it won't be called and obviously it can't do its work.

You have to call defer first and then the explode() function:

defer func() {
    // recover() here, Your code omitted
}()
explode()

Try it on the Go Playground.

答案2

得分: 0

对于更多的情况,"panic"只能在同一个例程中被"recover",不能在外部被恢复。

https://play.golang.org/p/e7-3SU2Cvss

英文:

for something more, "panic" could only be "recover" within the same routine, it couldn't be recovered outside.

https://play.golang.org/p/e7-3SU2Cvss

huangapple
  • 本文由 发表于 2015年2月11日 17:59:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/28451380.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定