22.异常处理
error接口定义如下:
1: type error interface {
2: Error() string
3: }
Go语言的标准库代码包errors为用户提供如下方法:
1: package errors
2:
3: type errorString struct {
4: text string
5: }
6:
7: func New(text string) error {
8: return &errorString{text}
9: }
10:
11: func (e *errorString) Error() string {
12: return e.text
13: }
另一个可以生成error类型值的方法是调用fmt包中的Errorf函数:
1: package fmt
2: import "errors"
3:
4: func Errorf(format string, args ...interface{}) error{
5: return errors.New(Sprintf(format,args...))
6: }
7:
简单代码示例:
1: package main
2: import (
3: "errors"
4: "fmt"
5: )
6:
7: func main() {
8: var errl error = errors.New("a normal errl")
9: fmt.Println(errl)
10:
11: var err2 error = fmt.Errorf("%s", "a normal err2")
12: fmt.Println(err2)
13: }
error接口的应用
1: package main
2: import "fmt"
3: import "errors"
4:
5: func MyDiv(a, b int) (result int, err error){
6: err = nil
7: if b == 0 {
8: err = errors.New("被除数不能为0")
9: }else {
10: result = a/b
11: }
12: return
13: }
14:
15: func main() {
16: result, err := MyDiv(8, 0)
17: if err != nil{
18: fmt.Println("err=", err)
19: } else {
20: fmt.Println("result=", result)
21: }
22: }
panic函数
某些不应该发生的场景发生时,我们就应该调用panic。当panic异常发生时,程序会中断运行,并立即执行在该goroutine。随后程序崩溃并输出日志信息。日志信息包括panic 。value的函数调用的堆栈跟踪信息。
panic函数接受任何值作为参数
1: func panic(v interface{})
调用panic函数引发的panic异常
1: func TestA() {
2: fmt.Println("func TestA{}")
3: }
4: func TestB() {
5: panic("func TestB():panic")
6: }
7:
8: func TestC() {
9: fmt.Println("func TestC()")
10: }
11:
12: func main() {
13: TestA()
14: TestB() //发生异常,中断程序
15: TestC()
16: }
1: >>> func TestA{}
2: panic: func TestB():panic
数组越界会自动调用panic
1: func TestA() {
2: fmt.Println("func TestA{}")
3: }
4: func TestB(x int) {
5: var a [10]int
6: a[x] = 111
7: }
8:
9: func TestC() {
10: fmt.Println("func TestC()")
11: }
12:
13: func main() {
14: TestA()
15: TestB(20) //发生异常,中断程序
16: TestC()
17: }
1: >>> func TestA{}
2: panic: runtime error: index out of range
recover函数的使用
panic异常会导致程序崩溃。而recover函数专门用于“拦截”运行时的panic异常,它可以是当前程序从运行时panic的状态中恢复并重新获得流程控制权。
1: func recover() interface{}
PS:recover只有在defer调用的函数中有效。
果调用了内置函数recover,并且定义该defer语句的函数发生了panic异常,recover会使程序从panic中恢复,并返回panic value。导致panic异常的函数不会继续运行,但能正常返回。在未发生panic时调用recover,recover会返回nil。
1: func TestA() {
2: fmt.Println("func TestA{}")
3: }
4:
5: func TestB() (err error) {
6: defer func() {
7: if x:= recover(); x!=nil{
8: err = fmt.Errorf("internal error:%v", x)
9: }
10: }() // 调用匿名函数
11: panic("func TestB():panic")
12: }
13:
14: func TestC() {
15: fmt.Println("func TestC")
16: }
17:
18: func main() {
19: TestA()
20: err:=TestB()
21: fmt.Println(err)
22: TestC()
23: }
24:
25: >>> func TestA{}
26: internal error:func TestB():panic
27: func TestC