错误

在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 关键字修饰的函数,会在主函数退出前被执行。