# Go语言panic, recover

### panic

* 停止当前函数执行
* 一直向上返回，执行每一层的defer
* 如果没有遇见recover，程序退出

### recover

* 仅在defer中调用
* 获取panic的值
* 如果无法处理，可以重新panic

```go
package main

import (
	"fmt"
)

func tryRecover() {
	defer func() {
		r := recover()
		if r == nil {
			fmt.Println("Nothing to recover. " +
				"Please try uncomment errors " +
				"below.")
			return
		}
		if err, ok := r.(error); ok {
			fmt.Println("Error occurred:", err)
		} else {
			panic(fmt.Sprintf(
				"I don't know what to do: %v", r))
		}
	}()
	panic(errors.New("this is an error"))

func main() {
	tryRecover()
}

```

```
Error occurred: this is an error
```

系统的panic也可以捕捉到。

```go
b := 0
a := 5 / b
fmt.Println(a)
```

```
runtime error: integer divide by zero
```

但是`panic()`的参数是`interface{}，`可以传入任何值，而`recover()`的返回值也是`interface{}`，所以recover不知道如何处理的时候需要继续panic处理。

加入传入一个`panic(123)`

```
panic: 123 [recovered]
        panic: I don't know what to do: 123

goroutine 1 [running]:
main.tryRecover.func1()
        /Users/ding/go/coding-180/lang/errhandling/recover/recover.go:19 +0x1e0
panic(0x10a2ca0, 0x10d8850)
        /usr/local/Cellar/go/1.11.4/libexec/src/runtime/panic.go:513 +0x1b9
main.tryRecover()
        /Users/ding/go/coding-180/lang/errhandling/recover/recover.go:35 +0x55
main.main()
        /Users/ding/go/coding-180/lang/errhandling/recover/recover.go:39 +0x20
exit status 2
```









