go-defer

1.defer基础应用:延迟调用,后进先出,异常处理

场景:打开连接/关闭连接,加锁/释放锁,打开文件/关闭文件

func main() {
	for i := 0; i < 6; i++ {
		defer log.Println("EDDYCJY" + strconv.Itoa(i) + ".")
	}

	log.Println("end.")
}
func main() {
	for i := 0; i < 6; i++ {
		defer log.Println("EDDYCJY" + strconv.Itoa(i) + ".")
	}

	log.Println("end.")
}

2.底层实现

1.协程记录defer信息,退出时调用。

①堆上分配(大部分情况):在堆上开辟一个sched.deferpool,遇到defer语句就将信息放进这个pool里面,在p结构体里面。

type p struct {
	····
	deferpool    []*_defer // pool of available defer structs (see panic.go)
	deferpoolbuf [32]*_defer

在函数退出的时候,从deferpool中取出执行。

问题:放在堆上,涉及到垃圾回收问题。

②:栈上分配:遇到defer语句,将信息放到栈上,函数返回的时候从栈中取出执行。

好处:没有堆上垃圾回收问题。

问题:栈上空间有限,所以不能最多只能保存一个defer信息。

2.将defer编码直接编至函数尾

①开放编码:如果defer语句在编译的时候就可以固定,就直接改写用户代码,将defer语句放入函数末尾,这种效果最好但是能优化的可能性最小。

3.recover与panic

panic 是 Go 中的一个内置函数,可用于停止程序的正常执行并开始 panic。当 panic 发生时,程序停止当前的执行并开始展开堆栈,执行所有延迟函数,直到到达堆栈顶部。然后,它会打印 panic 消息并退出。

recover 是 Go 中的另一个内置函数,可用于从 panic 中恢复。当在defer函数内部调用 recover 时,它会停止堆栈的展开并返回传递给 panic 函数的值。如果在延迟函数之外调用 recover 或者没有 panic 发生,它会返回 nil

以下是使用 panicrecover 的示例:

func main() {
    defer func() {
        if r := recover(); r != nil {
            log.Println("recovered from panic:", r)
        }
    }()

    var a []int
    a[1] = 1
}

在此示例中,程序尝试为未初始化的切片分配一个值,从而导致 panic。但是,defer 函数从 panic 中恢复并记录一条消息,而不是使程序崩溃。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乔可南-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值