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机制。