Golang漂亮的错误处理规范也是Go语言的最大亮点之一。
error接口
标准库把error定义为接口类型, 以便于自己定义错误类型
type error interface{
Error() string
}
error的使用也比较简单
// error对象的两种创建方式
// 1.使用fmt.Errorf
//var err1 error = fmt.Errorf("%s", "this is normal error")
err1 := fmt.Errorf("%s", "this is normal error")
fmt.Println("err1 = ", err1)
// 2. 使用errors.New()创建
err2 := errors.New("this is normal error2")
fmt.Println("err2 = ", err2)
再看看error的基本使用。
对于大多数函数,如果要返回错误,大致都可以定义为如下模式,将error作为返回值的最后一个,但这并非是强制要求的:
func Foo (param int) (n int, err error) {
//...
}
调用时的代码建议按照如下的方式进行处理错误
n, err := Foo(0)
if err != nil {
// 错误处理
} else {
// 使用返回值n进行逻辑处理
}
举个栗子说明一下:
func TestUseError() {
result, err := MyDiv(10, 0)
if err != nil {
// err不为空,那就说明出错了,那就打印错误信息
fmt.Println("err = ", err)
} else {
// err为空,那就说明没有错误,那就打印结果
fmt.Println("result = ", result)
}
}
func MyDiv(a, b int) (res int, err error) {
if b == 0 {
err = errors.New("分母不能为0")
} else {
res = a / b
}
return
}
自定义error类型
因为Go语言接口的灵活性,根本不需要从error接口继承或者像Java一样使用implement来声明继承自哪个接口,具体代码如下:
type pathError struct {
Op string
Path string
Err error
}
func (e *Patherror) Error() string {
return e.Op + " " + e.Path + ": " + e.Err.Error()
}
panic()和recover()
Go语言中有两个内置函数panic()和recover()用来报告和处理运行时错误和程序中的错误。
- error用于返回错误信息
- panic()函数用于处理运行时异常,例如下标越界,空指针等,当panic异常发生时,程序会中断运行
- recover()函数用于终止错误处理流程,也就是可以用来捕获并返回panic提交的错误内容,并使程序不要中断运行,但是recover()函数必须在defer中设置(连续调用panic,仅仅最后一个会被recover捕获)
一般recover的代码模板为:
defer func() {
if err:= recover(); err != nil {
fmt.Println(err)
}
}()
foo()
// 无论foo()中是否会触发错误处理流程,该匿名defer函数都会在函数退出时得到执行。
// 假如foo()触发了错误处理流程,recover()函数执行将会使得该错误流程终止。
// 如果错误处理流程被触发,程序传给panic函数的参数不为nil,那么err中存的错误信息将会被打印出来。
下面在实践中体会一下panic和recover的使用
func TestUsePanicAndRecover() {
test1()
test2(20)
test3()
}
func test1() {
fmt.Println("1111111111111111111")
}
func test2(x int) {
//如果不想让程序崩溃,那就需要设置一个recover()函数
defer func() {
//recover() // 直接调用recover()函数,结果就是这段代码直接跳过
// 选择打印recover(),这样就可以把panic中的错误信息打印出来
if err := recover(); err != nil {
// 这里加一个判断,如果这里出错了,那么err就不为空,那就打印recover中的内容,否则
fmt.Println(err)
}
}() // () 在这里是调用匿名函数
var a [10]int
a[x] = 100000 //这里会报一个数组下标越界的异常,产生一个panic,导致程序崩溃
}
func test3() {
fmt.Println("3333333333333333333333")
}