异常就是程序出现了不正常的情况,会导致程序非正常停止,而异常处理就是针对非正常停止的情况,给出异常时的处理方式。语法错误不算异常体系中
- error是一个接口,作用是返回程序异常的信息,errors实现了error
- 创建error使用errors.New()可以定义异常信息
- 如果将error作为返回值的话,要放在返回值列表的最后
演示:
func TestError(num1, num2 int) (result int, err error) { err = nil if num1 == 0 || num2 == 0 { fmt.Println("除数不能为0") return } result = num1 / num2 return } func main() { num, err := TestError(10, 1) if err != nil { err = errors.New("除数不能为0") } else { fmt.Println(num) } }
标准库将error定义为接口类型,以便于实现自定义错误类型
type error interface { Error() string }
error是最后一个返回参数。标准库提供了相关创建函数, 含简单错误文本的error对象
func main() { z, err := div(5, 0) if err == errDivByZero { log.Fatalln(err) } println(z) } var errDivByZero = errors.New("division by zero") func div(x, y int) (int, error) { if y == 0 { return 0, errDivByZero } return x / y, nil }
错误变量通常以err作为前缀,且字符串内容全部小写,没有结束标点,以便于嵌入到其他格式化字符串中输出。与errors.New类似的还有fmt.Errorf,它返回一个格式化内容的错误对象。某些时候,我们需要自定义错误类型,以便容纳更多上下文状态信息。如此,还可基于类型做出判断
func main() { z, err := div(5, 0) if err != nil { switch e := err.(type) { // 根据类型匹配 case DivError: fmt.Println(e, e.x, e.y) default: fmt.Println(e) } log.Fatalln(err) } println(z) } type DivError struct { x, y int } //自定义错误类型。 func (DivError) Error() string { return "division by zero" } //实现error接口方法。 func div(x, y int) (int, error) { if y == 0 { return 0, DivError{x, y} } //返回自定义错误类型。 return x / y, nil }
panic是内置函数,可以终止程序,会立即中断当前函数流程,触发执行延迟调用
recover可以拦截panic异常信息,但是recover不可以直接调用,只有在defer调用的函数中有效
如果是放在循环中了,连续调用panic,仅最后一个会被recover捕耕
func main() { defer func() { if err := recover(); err != nil { // 捕捉错误 log.Fatalln(err) } }() panic("我挂了") // 引发错误 fmt.Println("会走这一步吗") // 不会执行,编译器也会提示这是一个永远不会执行的代码 }
除非是不可恢复性,导致系统无法正常工作的错误,否则不建议使用Panic
例如:文件系统没有操作权限,服务端口被占用,数据库未启动等情况