Go基础学习-defer

defer执行的原则

  1. defer延迟函数总是在异常panic或者正常return前返回;
  2. defer执行顺序按照先入后出的原则,即先入栈的最后执行;但是会先把参数压入栈,具体执行会在函数结束前
  3. 当defer函数中存在函数时会先执行里面的函数;
  4. defer函数调用的参数当存在闭包时,会从外面拿取该参数的最新的值;
  5. defer常常与recover一同使用;用来做异常捕捉后的延迟执行;从而将异常给转换为错误error;

看几个案例:
案例1:

func main() {
	i := 10
	defer fmt.Printf("defer i=%d", i) 
	i = 100
	fmt.Println(i)
}
/*
output:
100
defer i=10
*/

用到原则1、2

案例2:

func calc(x,y int )int{
	res:=x+y
	fmt.Println(x,y,res)
	return res
}

func main(){
	a:=10
	b:=20
	defer calc(a,calc(a,b))
	a=100
	defer calc(a,calc(a,b))
	a=1000

}
//output:
//10 20 30
//100 20 120
//100 120 220
//10 30 40

使用到原则1,2,3

案例3:

func calc(x,y int )int{
	res:=x+y
	fmt.Println(x,y,res)
	return res
}
func main(){
	a:=10
	b:=20
	defer func(i int) {
		calc(a,calc(a,b))
		fmt.Println(i)
	}(1000)
	a=100
}

//闭包的原理:a会从函数外面找最新的那个值,这个区别于main2中的压栈执行(先将a传进去,等待执行);
//output:
//100 20 120
//100 120 220
//1000

使用到原则1,2,3,4

案例4:

func divi(x,y int) (z int,err error){
	defer func() {
		if e := recover();e!=nil{
			err =e.(error)
		}
	}()
	z = x / y
	return z ,nil
}
/*
input:divi(1,0)
output:
0 runtime error: integer divide by zero
*/

使用到原则1,2,3,5

案例5:

func main() {
	println(DeferFunc1(1))
	println(DeferFunc2(1))
	println(DeferFunc3(1))
}
func DeferFunc1(i int)(t int) {
	t = i
	defer func() {
		t += 3
	}()
	return t
}
func DeferFunc2(i int)int {
	t := i
	defer func() {
		t += 3
	}()
	return t
}
func DeferFunc3(i int)(t int) {
	defer func() {
		t += i
	}()
	return 2
}
/*
output:
4 1 3
*/

使用到原则1;
此外对于返回值如果在返回参数中声明了变量,那们他就是全局的;
按照此原则,DeferFunc1;t被全局声明,在返回前调用defer,返回4;DeferFunc2中
t在函数内部声明,defer相当于闭包调用了外面的t,相当于赋值黏贴改的不是指针;所以返回的是1;DeferFunc3中t全局声明了 ,此外return 2相当于给t赋值为2;之后再调用defer,所以返回的是3

案例6:

func main() {
	defer func() {
		if err:=recover();err!=nil{
			fmt.Println("++++")
			f:=err.(func()string)
			fmt.Println(err,f(),reflect.TypeOf(err).Kind().String())
		}else {
			fmt.Println("fatal")
		}
	}()
	defer func() {
		fmt.Println("-----")
		panic (func()string {
			return "defer panic"
		})
	}()
	panic("panic")
}

/*
-----
++++
0x49abd0 defer panic func
*/

panic仅有最后一个可以被revover捕获
触发panic(“panic”)后顺序执行defer,但是defer中还有一个panic,所以覆盖了之前的panic(“panic”)

猜你喜欢

转载自blog.csdn.net/wzb_wzt/article/details/107796409