Go语言--语法基础8--函数定义与调用--错误处理
Go 语言异常处理详解(error - 错误、panic - 恐慌、recover - 恢复)
在 Go 语言中,异常处理主要通过 error
、panic
和 recover
三个机制来实现,它们分别用于处理不同级别的错误情况。
1、error:处理非致命错误
error
一般用于处理一些比较低级的错误,不会造成程序中断或者宕机。Go 标准库提供了创建错误的函数。
简单使用标准库的错误函数
package main
import ("errors""fmt"
)
func main() {err1 := fmt.Errorf("%s", "this is a Errorf")fmt.Println("err1: ", err1)err2 := errors.New("this New error")fmt.Println("err2: ", err2)
}
error 常用用法
通常在函数返回时携带错误信息,通过判断 error
是否为 nil
来确定操作是否成功:
package main
import ("errors""fmt"
)// error 为 nil 说明正常,否则报错,信息从 errors.New 获取
func MyDiv(a, b int) (result int, err error) {err = nilif b == 0 {err = errors.New("分母不能为0")} else {result = a / b}return // 等价于 return result, err
}func main() {ret, err := MyDiv(2, 2)if err == nil {fmt.Println("ret = ", ret)} else {fmt.Println("表达式存在非法值, err: ", err)}ret, err = MyDiv(2, 0)if err == nil {fmt.Println("ret = ", ret)} else {fmt.Println("表达式存在非法值, err: ", err)}
}
errors.New
函数的实现原理:
func New(text string) error {return &errorString{text}
}
通过这个函数获取一个 errorString
结构,从而可以调用 Error
方法。
2、panic:处理致命错误
panic
一般在发生致命错误时被调用,例如数组越界、空指针等,我们也可以手动调用 panic()
函数触发。它类似于 C 语言的 assert()
断言函数。
2.1 手动调用 panic
package main
import "fmt"func testa() {fmt.Println("aaaaaaaaaaaaaa")
}func testb() {fmt.Println("bbbbbbbbbbbbbb")// 手动调用 panic() 会触发断言panic("manual triggered assertions, the program breaks")
}func testc() {fmt.Println("ccccccccccccccc")
}func main() {testa()testb()testc() // 这行代码不会执行,因为程序已被 panic 中断
}
结果:
aaaaaaaaaaaaaa
bbbbbbbbbbbbbb
panic: manual triggered assertions, the program breaksgoroutine 1 [running]:
main.testb().../main.go:11 +0x65
main.main().../main.go:19 +0x50
exit status 2
2.2 数组越界造成 panic
package main
import "fmt"func testa() {fmt.Println("aaaaaaaaaaaaaa")
}func testb(index int) {// 数组越界造成 panic 断言var x [10]intfmt.Println("x: ", x[index])
}func testc() {fmt.Println("ccccccccccccccc")
}func main() {testa()testb(10) // 数组越界触发断言testc() // 这行代码不会执行
}
结果:
aaaaaaaaaaaaaa
panic: runtime error: index out of range [10] with length 10goroutine 1 [running]:
main.testb(0xa).../main.go:10 +0x5f
main.main().../main.go:18 +0x50
exit status 2
3、recover 函数:恢复程序执行
当发生 panic
错误时,程序会中断执行。但有时候我们希望捕获这个中断,让程序继续运行,这时可以使用 recover
函数。
注意:recover()
只有在 defer
调用的函数中才有效。当函数中定义了 defer
,并且该函数发生了 panic
错误,recover
可以捕获该错误,使程序恢复正常。
package main
import "fmt"func testa() {fmt.Println("aaaaaaaaaaaaaa")
}func testb(index int) {// 设置 recoverdefer func() {if err := recover(); err != nil {// 不要再次调用 recover() 作为信息,因为错误已经被捕获fmt.Println("errInfo: ", err)}}()// 数组越界造成 panic 断言var x [10]intfmt.Println("x: ", x[index])
}func testc() {fmt.Println("ccccccccccccccc")
}func main() {testa()testb(10) // 数组越界触发断言,但会被 recover 捕获testc() // 这行代码会正常执行
}
结果:
aaaaaaaaaaaaaa
errInfo: runtime error: index out of range [10] with length 10
ccccccccccccccc
通过 recover
捕获 panic
后,程序会从 panic
发生的地方继续向下执行,而不会中断整个程序。这在需要容错处理的场景中非常有用。