defer,panic,recover

Go语言不支持传统的 try…catch…finally 这种异常,因为Go语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得混乱。因为开发者很容易滥用异常,甚至一个小小的错误都抛出一个异常。在Go语言中,使用多值返回来返回错误。不要用异常代替错误,更不要用来控制流程。在极个别的情况下,也就是说,遇到真正的异常的情况下(比如除数为0了)。才使用Go中引入的Exception处理:defer, panic, recover。流程可以简要描述为:在代码片段中抛出一个panic的异常,然后在defer中通过recover捕获这个异常,然后正常处理

一.使用多返回值来处理错误

import (
	"errors"
	"fmt"
)

func Handle(i int) (int, error) {
	if i == 0 {
		return i, errors.New("除数为0")
	}
	return 100 / i, nil
}

func main() {
	if divint, err := Handle(0); err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(divint)
	}
}

  

二.defer

defer就是用来添加函数结束时执行的语句.因为这个特性,可以将其用作关闭文件句柄等.

func Handle(i int) (res int) {
	res = i
	defer func() {
		res++
	}()
	return res
}

func main() {
	i := Handle(0)
	fmt.Println(i)
}

  

打印出1, 因为defer中添加了一个函数,在函数返回前改变了命名返回值的值.如果defer语句没有执行,那么defer函数不会添加.

func Handle(i int) (res int) {
	res = i
	return res // 直接返回了,defer没有执行
	defer func() {
		res++
	}()
	return res
}

func main() {
	i := Handle(0)
	fmt.Println(i)
}

  

二.panic


panic 是用来表示非常严重的不可恢复的错误的.可以理解为一般语言的 throw new Exception().调用panic看看,程序立马挂掉,然后Go运行时会打印出调用栈.
关键的一点是,即使函数执行的时候panic了,函数不往下走了,运行时并不是立刻向上传递panic,而是到defer那,等defer的东西都跑完了,panic再向上传递。所以这时候 defer 有点类似 try-catch-finally 中的 finally。\

 

三.recover


捕获panic,被捕获到的panic就不会向上传递了.不过要注意,recover之后,逻辑并不会恢复到panic那个点去,函数还是会在defer之后返回.

用Go实现类似 try catch 的异常处理:

 

import (
	"fmt"
)

func Handle(i int) (res int) {
	if i == 0 {
		panic("被除数为0")
	}
	res = i / 2
	return res
}

func main() {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println(err)
		}
	}()
	Handle(0)
}

  

 

posted @ 2017-10-07 16:45  rorshach  阅读(144)  评论(0编辑  收藏  举报