从Golang应用程序的恐慌中恢复(附实例)

218 阅读1分钟

恐慌是为了使应用程序崩溃,这是默认的行为。然而,如果你想防止这种情况发生,让你的应用程序继续运行,就像什么都没有发生一样,你将不得不使用recover 功能。规则是,只有当你想恢复时才恢复。简而言之,不要默认恢复每一次恐慌。相反,通过检查恐慌类型有选择地恢复。**注意:**对于诸如应用程序耗尽内存的情况,没有恢复功能。

例子

没有恢复的恐慌

如下图所示,应用程序崩溃了:

func main() {
	fmt.Println("main: begin")

	panic("Main function panicked!")

	fmt.Println("main: end")
}

// Output:
// main: begin
// panic: Main function panicked!
//
// goroutine 1 [running]:
// main.main()
// /Users/mysql/Server/Go/src/github.com/inanzzz/client/cmd/client/main.go:4 +0xb3
// exit status 2

从所有恐慌中恢复

如下图所示,应用程序从恐慌中恢复过来,没有崩溃:

func main() {
	defer func() {
		if p := recover(); p != nil {
			fmt.Println("main: recovered from panic")
		}
	}()

	fmt.Println("main: begin")

	panic("Main function panicked!")

	fmt.Println("main: end")
}

// Output:
// main: begin
// main: recovered from panic

有选择地从恐慌中恢复

如下图所示,应用程序从good 恐慌类型中恢复,但没有恢复其他类型:

type good struct {}
type bad struct {}

func main() {
	defer func() {
		switch p := recover(); p {
		case nil:
		case good{}:
			log.Printf("recovered from %T\n", p)
		case bad{}:
			panic(p)
		default:
			panic(p)
		}
	}()

	fmt.Println("main: begin")

	//panic(good{})
	//panic(bad{})
	//panic("something else")

	fmt.Println("main: end")
}

// Output for no panic at all.
// main: begin
// main: end

// Output when panic(good{}) is enabled.
// main: begin
// 2020/01/10 22:27:54 recovered from main.good

// Output when panic(bad{}) is enabled.
// main: begin
// ...
// /Users/inanzzz/Server/Go/src/github.com/inanzzz/client/cmd/client/main.go:11 +0xda
// ...
// exit status 2

// Output when panic("something else") is enabled.
// main: begin
// ...
// /Users/inanzzz/Server/Go/src/github.com/inanzzz/client/cmd/client/main.go:13 +0xda
// ...
// exit status 2