Go通关07:错误处理,如何通过error/panic处理错误?
错误
在Go语言中,错误并不是非常严重,它是可以预期的,可以返回错误给调用者自行处理。
error 接口
在Go语言中,错误是通过内置的error接口来表示的,它只有一个Error方法来返回错误信息:
type error interface {
Error() string
}
这里演示一个错误的示例:
func main() {
i,err := strconv.Atoi("a")
if err != nil {
fmt.Println(err)
}else {
fmt.Println(i)
}
}
- 示例故意使用错误的字符串“a”来转为整数,所以这里会打印错误信息:
strconv.Atoi: parsing "a": invalid syntax
- 一般,error接口在当函数或方法调用时遇到错误时进行返回,且为第二个返回值,这样调用者就可以根据错误来自行处理。
error 工厂函数
我们可以使用 errors.New 这个工厂函数来生成错误信息,它接收一个字符串参数,返回一个error接口。
func test(m,n int) (int, error) {
if m > n {
return m,errors.New("m大于n")
}else {
return n,nil
}
}
当m大约n的情况下,返回一个错误信息。
自定义 error
上面工厂函数只能传递一个字符串来返回,要想携带更多信息,这时候可以使用自定义error:
type testError struct {
errorCode int //错误码
errorMsg string //错误信息
}
func (t *testError) Error() string{
return t.errorMsg
}
这里自定义error,它可以返回更多信息:
return m, &testError{
errorCode: 1,
errorMsg: "m大于n"}
上面通过字面量方式创建*testError 来返回。
error 断言
通过error断言来获取返回的错误信息,断言可以将error接口转为自己定义的错误类型:
res, err := test(2,1)
if e,ok := err.(*testError);ok {
fmt.Println("错误码:",e.errorCode,",错误信息:",e.errorMsg)
} else {
fmt.Println(res)
}
Panic 异常
Go语言是一门静态语言,很多错误可以在编译的时候进行捕获,不过对于数组越界访问、不同类型强制转换这种,会在运行时候才会引起panic异常。
我们也可以手动来抛出 panic 异常,这里以连接mysql数据库为例:
func connectMySQL(ip,username,password string){
if ip =="" {
panic("ip不能为空")
}
//省略其他代码
}
- 在以上函数中,如果ip地址为空,会抛出 panic 异常。
- panic 是Go语言内置函数,可以接收 interface{} 类型的参数,也就是说任何类型的值都是可以传递给 panic 函数的:
func panic(v interface{})
interface{} 表示空接口,代表任意类型。
panic 是一种非常严重的错误,会使程序中断执行,所以 如果不是影响程序运行的错误,使用 error 即可
Recover 捕获 Panic 异常
一般我们不对panic异常做处理,但是如果有一些需要在程序崩溃前做处理的操作,可以使用内置的 recover 函数来恢复 panic 异常。
程序 panic 异常崩溃的时候,只有defer修饰的函数才会被执行,所以 recover 函数要结合 defer 关键字一起使用:
func main() {
defer func() {
if p:=recover();p!=nil{
fmt.Println(p)
}
}()
connectMySQL("","root","123456")
}
recover 函数捕获了 panic 异常,打印:recover 函数返回的值就是通过 panic 函数传递的参数值。 ip不能为空
- recover 函数的返回值就是 panic 函数传递的参数值。
- defer 关键字修饰的函数,会在主函数退出前被执行。