ch2-defer

defer的作用?

可以让defer后的语句在当前函数执行完成后执行。应用场景:在打开文件下一场使用defer避免忘记关闭。但是,defer具有短暂延迟,对于高性能的程序尽量避免使用。

defer的执行顺序?

代码执行遇到defer语句,将defer后的函数注册。外层函数退出后,函数内注册过的函数逆序执行(先注册、后执行)。当注册的函数为nil时,会panic。

defer后的函数引用外部变量有两种方式:

  1. 函数参数:函数参数分为值参数和引用参数。值参数,defer函数里的值和传入的一样。而引用参数,外部的变量改变时,defer函数里的也会变化。
  2. 闭包:defer函数使用到变量是会根据上下文确定变量的。

在return之后的defer语句无法完成注册。

return的拆解?

return 语句可以被分解成3个语句执行的:

  1. X = XXX 赋值
  2. 调用defer函数
  3. return
func f()(r int) {
	defer func(r int) {
		r := r + 1
	}(r)
  return 1
}

上述代码实际转化为下面的代码:

func f()(r intr) { 
  r = 1
	func(r int) {
		r := r + 1
	}(r)
  return
}

闭包是什么?

闭包=函数+引用环境,匿名函数也被称为闭包,闭包捕获的变量是引用传递。

defer如何配合recover?

需要再defer的函数中调用。

func  main(){
	defer recover()
	panic(404)
}

不可以。

func  main(){	
	defer func (){
		recover()
	}
	panic(404)
}

可以。

defer函数的执行流程?

在G(goroutine)执行过程中,遇到defer后调用deferporc函数创建_defer(创建_defer首先G绑定的P的_defer pool取,如果没有再到全局的_defer pool中取。)结构体,以链表的形式挂在到G上。

在RET指令执行之前,会调用deferreturn函数,deferreturn执行完毕之前调用jumpderfer,jumpdefer会跳转到之前defered的函数。执行完毕,控制权再次转交给runtinme。deferreturn继续执行其他defered函数。

为什么无法从父goroutine中恢复字goroutine的panic?

每个goroutine都有自己独立的执行栈,不与其他goroutine共享数据。goroutine没有自己的ID、返回值。

但可以通过全局panic捕获实现。

var notifier chan interface{}
func startGlobalPanicCapturing(){
	notifier = make(chan interface{})
	go func() {
		for {
			select {
			case r := <-notifier:
				fmt.Println(r)
			}
		}
	}()
}
func main()  {
	startGlobalPanicCapturing()
	Go(func() {
		a:=make([]int, 1)
		fmt.Println(a[1])
	})
}
func Go(f func())  {
	defer func() {
		if r := recover(); r != nil{
			notifier<-r
		}
	}()
	f()
}

使用上述方式恢复goroutine有局限性,需要强制f中的goroutine都用Go创建。而且也会遇到不能恢复panic,如:并发读写map。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值