错误处理
前言
在Go语言中,错误和异常是不同的概念,分错误error
和异常panic
两种。error
一般是程序开发者预知的,会进行适当的处理,比如检测用户输入不合法,抛出一个error
错误。panic
是程序开发者无法预知的异常,比如引用的对象值为空。
类似于try...catch...finally
,go语言的错误处理机制是用defer
、panic
和recover
。
Go包含了一个独立的错误处理类型,即error
,如果认为默认的不够完善,那么也可以创建自定义错误消息。
Go语言中的错误不同于其它编程语言中的异常或错误,它们被定义为一个普通对象,并像其他值那样可以从函数或方法中返回。
error
在许多情况下,当开发自己的Go应用程序时,我们可能需要处理新的错误情形。对此,Go语言提供了两种创建error
的方法,它们底层是一样的,只是一种带格式,一种不带格式。
errors.New
fmt.Errorf
示例1:
func ErrorUsage() {
err := errors.New("err: found 1")
if err != nil {
fmt.Println(err.Error())
}
err2 := fmt.Errorf("err: %s", "found 2")
if err2 != nil {
fmt.Println(err2.Error())
}
}
示例2:
package main
import (
"errors"
"fmt"
)
func returnError(a, b int) error {
if a == b {
err := errors.New("Error in returnError function")
return err
} else {
return nil
}
}
func main() {
err := returnError(1, 1)
if err != nil {
fmt.Println(err)
}
}
示例代码:计算倒数
package main
import (
"errors"
"fmt"
)
func reciprocal(n int) (float64,error) {
// 计算倒数
if n == 0 {
return 0,errors.New("0不能为倒数")
}
return float64(1) / float64(n), nil
}
func main() {
for i := 3;i >= 0;i-- {
ret,err := reciprocal(i)
// 对于函数返回值有错误error的情况下,要先判断一下函数有没有error。
// 如果有error,就把错误信息打印到控制台,否则输出计算得到的倒数值
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("1/%d = %.3f\n",i,ret)
}
}
}
error
作为函数的返回值,应放在返回值类型列表的末尾。
panic
在没有recover
的情况下,panic
会导致程序连带主协程及其它协程一起崩溃。
示例代码01
package main
import "fmt"
func div(a,b int) (int,error) {
if b == 0 {
panic("除数不能为0")
}
return a/b,nil
}
func main() {
a := 12
b := 0
defer func() {
err := recover()
if err != nil {
fmt.Println("异常被捕获到")
fmt.Println("helloworld")
}
}()
fmt.Println(div(a,b))
}
当div(a/b)
引起panic
异常,后面的代码不会执行,但还是会触发defer
,在defer
中通过recover()
对异常进行捕获。
示例代码02
package main
import (
"fmt"
)
func recoverPanic() {
// doPanic: 当捕获panic异常时触发
// 调用内置的recover()捕获panic异常
err := recover()
if err != nil {
// runtime error: integer divide by zero
fmt.Println("doPanic()捕获到异常:", err)
}
}
func main() {
// 注册捕获异常的处理函数
defer recoverPanic()
n := 0
ret := 1 / n
// 出现异常后,下面语句不会执行打印
fmt.Println("main ret = ",ret)
}
- 在
Go
语言中,recover
只在defer
调用的函数中有效,并且defer
要先注册,否则不能捕获到panic
异常。