13-错误与异常(go基础)
错误与异常
错误
Go 语言通过内置的错误接口提供了非常简单的错误处理机制。
error类型是一个接口类型,这是它的定义:
1 | type error interface { |
error
有了一个签名为 Error() string
的方法。所有实现该接口的类型都可以当作一个错误类型。Error()
方法给出了错误的描述。fmt.Println
在打印错误时,会在内部调用 Error() string
方法来得到该错误的描述。
1 | package main |
我们这里没有存在一个文件 a.txt
,所以尝试打开文件将会返回一个不等于 nil
的错误。
自定义错误
1 | package main |
给错误添加更多信息
1 | package main |
异常
错误和异常是两个不同的概念,非常容易混淆。错误指的是可能出现问题的地方出现了问题;而异常指的是不应该出现问题的地方出现了问题。
panic
在有些情况,当程序发生异常时,无法继续运行。在这种情况下,我们会使用 panic
来终止程序。当函数发生 panic
时,它会终止运行,在执行完所有的延迟函数后,程序返回到该函数的调用方。这样的过程会一直持续下去,直到当前协程的所有函数都返回退出,然后程序会打印出 panic
信息,接着打印出堆栈跟踪,最后程序终止。
我们应该尽可能地使用错误,而不是使用 panic
和 recover
。只有当程序不能继续运行的时候,才应该使用 panic
和 recover
机制。
panic
有两个合理的用例:
- 发生了一个不能恢复的错误,此时程序不能继续运行。一个例子就是 web 服务器无法绑定所要求的端口。在这种情况下,就应该使用
panic
,因为如果不能绑定端口,啥也做不了。 - 发生了一个编程上的错误。假如我们有一个接收指针参数的方法,而其他人使用
nil
作为参数调用了它。在这种情况下,我们可以使用panic
,因为这是一个编程错误:用nil
参数调用了一个只能接收合法指针的方法。
触发 panic
下面是内建函数 panic
的签名:
1 | func panic(v interface{}) |
当程序终止时,会打印传入 panic
的参数。
1 | package main |
发生 panic 时的 defer
上面已经提到了,当函数发生 panic
时,它会终止运行,在执行完所有的延迟函数后,程序返回到该函数的调用方。这样的过程会一直持续下去,直到当前协程的所有函数都返回退出,然后程序会打印出 panic
信息,接着打印出堆栈跟踪,最后程序终止。
1 | package main |
recover
recover
是一个内建函数,用于重新获得 panic
协程的控制。下面是内建函数 recover
的签名:
1 | func recover() interface{} |
recover
必须在 defer
函数中才能生效,在其他作用域下,它是不工作的。在延迟函数内调用 recover
,可以取到 panic
的错误信息,并且停止 panic
续发事件,程序运行恢复正常。
1 | package main |