一架梯子,一头程序猿,仰望星空!

go语言错误处理


go语言中主要有两类错误,一类是可预见的错误,不会导致程序退出,一类是不可预见的错误,会导致程序退出。

在go语言中error是不会导致程序退出、panic会导致程序退出。

1.error基本用法

go语言内置了一个错误接口:

type error interface {
    Error() string
}

errors包提供了基本的错误实现

例如创建一个错误:

// 创建一个错误
errors.New("错误信息")

例子:

package main

import (
    "errors"
    "fmt"
)

// 通常一个函数的错误信息,都会放在最后一个返回值
func Do() (int, error) {
    // 返回错误
    return 0, errors.New("错误信息!")
}

func main() {
    _, err := Do()
    // 判断错误
    if err != nil {
        fmt.Println(err)
    }
}

提示:一般如果函数没有错误,返回的error就是nil。

2.自定义错误类型

我们只要实现错误接口,就可以自定义错误类型。

例子:

package main

import (
	"fmt"
	"time"
)

// 自定义错误类型MyError
type MyError struct {
    // 为新定义的错误类型,增加两个字段
    When time.Time // 错误发生的时间
    What string // 错误的原因
}

// 实现error接口的方法
func (e *MyError) Error() string {
	return fmt.Sprintf("at %v, %s",
		e.When, e.What)
}

// 测试自定义的错误
func run() error {
     // 创建一个自定义错误,并返回
    return &MyError{
	      time.Now(),
	      "it didn't work",
       }
}

func main() {
    if err := run(); err != nil {
	fmt.Println(err)
    }
}

3.panic用法

panic,类似其他语言throw抛出异常一样,通过函数调用链,一层层的把异常往上抛出去,如果没有人拦截异常,就会推出程序。

例子:

package main

import "fmt"

func main() {
    fmt.Println("a")

    // 抛出panic错误,后面的代码不会运行
    panic("出错啦!")

    fmt.Println("b")
}

运行输出:

a
panic: 出错啦!

goroutine 1 [running]:
main.main()
	/Users/tizi/Documents/demo/main.go:7 +0x95

panic会抛出一个panic错误,终止代码执行流程,然后逐层上报错误,直到被拦截,或者程序退出,一般都是慎用panic。

4.拦截panic错误

通过defer和recover实现拦截panic错误。

例子:

package main

import "fmt"

// 演示拦截panic错误
func Do() {
    // 延迟执行函数
    defer func() {
        // 在延迟执行函数中,通过recover拦截panic错误
        if err := recover(); err != nil {
            fmt.Println("拦截到错误:", err)
        }
    }()

    // 抛出panic错误,后面代码不会执行
    panic("panic错误")

    fmt.Println("b")
}

func main() {
    fmt.Println("a")

    Do()

    fmt.Println("c")
}

运行输出:

a
拦截到错误: panic错误
c

因为我们通过recover函数,在延迟执行函数中,拦截了Panic错误,除了抛出panic错误的函数被中断了,其他执行流程都不受影响,类似其他语言中的try/catch机制。