延迟语句defer
go版本 go1.14
defer的语义
defer会在函数返回、产生恐慌或者 runtime.Goexit 时被调用
defer的类型
在14版本中,有三种类型的defer:
在堆上分配的defer
在栈上分配的defer
开放编码式defer
// src/cmd/compile/internal/gc/ssa.go
func (s *state) stmt(n *Node) {
/.../
switch n.Op {
case ODEFER:
/../
if s.hasOpenDefers {//开放编码式
s.openDeferRecord(n.Left)
} else {
d := callDefer // 在堆上分配
if n.Esc == EscNever {
d = callDeferStack //在栈上分配
}
s.call(n.Left, d)
}
在堆上分配的defer
使用场景: 在循环语句种使用了defer, 或者无法执行更高阶的编译器优化
优点:在编译器
缺点:需要最多的运行时支持, 占用的运行时开销最大
在栈上分配的defer
使用场景:
defer 还可以直接在栈上进行分配,也就是第二种记录 defer 的形式 deferprocStack。 在栈上分配 defer 的好处在于函数返回后 _defer 便已得到释放, 不再需要考虑内存分配时产生的性能开销,只需要适当的维护 _defer 的链表即可。
开放编码式
//todo