跳到主要内容

错误处理

前言

在Go语言中,错误和异常是不同的概念,分错误error和异常panic两种。error一般是程序开发者预知的,会进行适当的处理,比如检测用户输入不合法,抛出一个error错误。panic是程序开发者无法预知的异常,比如引用的对象值为空。

类似于try...catch...finally,go语言的错误处理机制是用deferpanicrecover

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异常。