【defer】升级版1.13中的defer|Go主题月

217 阅读1分钟

1.13的defer

在1.13版本中,go语言改进了defer的创建。改为了直接用栈来存储_defer结构体。然后把栈上分配的_defer结构体注册到defer链表通过这样的方式避免在堆上分配_defer结构体。减少了堆和栈之间频繁复制导致的额外内存开销。

但是,值得注意的是,1.13版本中并不是所有defer都能够在栈上分配。循环中的defer,无论是显示的for循环,还是goto形成的隐式循环,都只能使用1.12版本中的处理方式在堆上分配。即使只执行一次的for循环也是一样。

例如:

//显示循环
for i:=0; i< n; i++{
    defer B(i)
}
......

//隐式循环
again:
    defer B()
    if i<n {
        n++
        goto again
    }

所以在1.13版本中也保存了1.12的defer特性。

图解

在新版本中_defer的结构体新加了一个字段heap用来判断结构是在堆上还是在栈上。然后通过编译,把_defer结构体分配到栈上,help字段设为false。其他执行步骤与1.12没有太大的差别。

defer1_13

除了分配位置的不同,栈上分配和堆上分配执行流程并没有本质的不同,而该方法可以适用于绝大多数的场景,与堆上分配相比,该方法可以将 defer 关键字的额外开销降低 30%。

前景回顾

大家也可以看看上篇文章介绍1.12版本的defer

【defer】1.12版本中的defer|Go主题月