> For the complete documentation index, see [llms.txt](https://yangsx95.gitbook.io/notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yangsx95.gitbook.io/notes/programming-language/golang/cuo-wu-chu-li.md).

# 错误处理

go语言没有异常，为了代码的优雅，也没有传统的`try catch finally`语法

```go
package main

import "fmt"

func main() {
	div(1, 0)
	fmt.Println("--- main执行完毕 ---")
}

func div(a, b int) int {
	return a / b
}
```

执行结果：

```
panic: runtime error: integer divide by zero   # 发生了一个panic（致命错误），会引发程序停止

goroutine 1 [running]: # 打印堆栈信息
main.div(...) 
        /Users/yangsx/Project/notes-golang/go语言圣经/练习答案/5. 函数/5.10 Recover捕获异常/练习 5.19/main.go:11
main.main()
        /Users/yangsx/Project/notes-golang/go语言圣经/练习答案/5. 函数/5.10 Recover捕获异常/练习 5.19/main.go:6 +0x12
```

为了程序正常运行，我们需要对错误进行处理。

## defer、panic、recover

* `panic`抛出错误
* `recover`在`defer`中捕获错误

## defer + recover 在方法内抓取错误

```go
package main

import "fmt"

func main() {
	div(1, 0)
	fmt.Println("--- main执行完毕 ---")
}

func div(a, b int) int {
	// 使用defer + recover 处理错误
	defer func() {
		// 如果该方法返回异常，则一定会走defer语句块，也就是这个闭包，可以在这个闭包中使用recover内置函数获取发生的异常对象
		if err := recover(); err != nil {
			fmt.Println("出现错误：", err)
			// 发送错误邮件....
		}
	}()
	return a / b
}
```

## panic抛出自定义错误

```go
package main

import (
	"errors"
	"fmt"
)

func main() {
	div(1, 0)
	fmt.Println("--- main执行完毕 ---")
}

func div(a, b int) int {
	if b == 0 {
	 	panic(errors.New("除数不能为0"))
	}
	return a / b
}
```

## 返回错误并交给调用方处理

代码预警，判断参数是否复合标准，否则创建一个自定error并返回

```go
package main

import (
	"errors"
	"fmt"
)

func main() {
	i, err := div(1, 0)
	if err != nil {
		fmt.Println("执行出现错误，程序退出：", err)
		return
	}
	fmt.Println("执行结果：", i)
}

func div(a, b int) (int, error) {
	if b == 0 {
		return 0, errors.New("除数不能是0")
	}
	return a / b, nil
}
```
