【defer】全新升级1.14以后的defer|Go主题月

简介: 在go1.14中,官方又对defer做了升级,据说这次升级把速度提升了一个量级。

网络异常,图片无法展示
|

1.14版本中的defer


go1.14中,官方又对defer做了升级,据说这次升级把速度提升了一个量级。

网络异常,图片无法展示
|

在编译期间,会直接把defer放到函数末尾去执行,省去了_defer结构体和链表的使用。官方把这种方法命名为:开放编码(Open Coded)

不过需要满足以下条件,否则并不会使用开放编码:

  • 函数的 defer 数量少于或者等于 8 个;
  • 函数的 defer 关键字不能在循环中执行;
  • 函数的 return 语句与 defer 语句的乘积小于或者等于 15 个;

延迟比特

为什么上面说defer的数量要小于等于8个呢?这是由于延迟比特的限制。延迟比特只有8个,默认值为0,每个对应一个defer,延迟比特的作用是判断defer语句到底要不要执行,例如:

package main
import "fmt"
func main() {
  i:=1
  if i==1{
    defer fmt.Println("defer")
  }
}

defer外面有一个if判断语句,当判断语句为true时,就会把对应的defer比特位设为1 。然后在函数末尾每个defer都会判断对应的比特位记录是否为1,如果为1就执行,否则就不执行。

网络异常,图片无法展示
|

使用时机

在当前版本中,defer一共有三种执行方式,那go到底是如何判断当前的defer是该用哪种方式呢?

代码生成阶段的 cmd/compile/internal/gc.state.stmt 会负责处理程序中的 defer,该函数会根据条件的不同,使用三种不同的机制处理该关键字:

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.callResult(n.Left, d)
    }func (s *state) stmt(n *Node) {
  ...
  }
}

panic问题

虽然最新版本中的defer速度非常快,但是当程序发送panic时,在这之后的正常逻辑就都不会执行了,而是直接去执行defer链表。那些使用**开放地址(open coded)在函数内展开,因而没有被注册到链表的defer函数要通过栈扫描的方式来发现。所以1.14版本中就添加了几个字段用来辅助panic的栈扫描。

网络异常,图片无法展示
|

回顾

目录
相关文章
|
4月前
|
Go
Go语言中defer的执行顺序详解
【2月更文挑战第22天】
75 4
|
2月前
|
监控 Kubernetes Go
全链路追踪 & 性能监控,GO 应用可观测全面升级
当前,大多数面向 Golang 应用的监控能力主要是通过 SDK 方式接入,需要开放人员手动进行埋点,会存在一定问题。对此,可观测 Go Agent 应运而生。本文介绍的阿里云可观测 Go Agent 方案,能通过无侵入的方式实现应用监控能力。
108409 25
|
1月前
|
存储 Go
掌握 Go 语言的 defer 关键字
掌握 Go 语言的 defer 关键字
|
22天前
|
Go
实验深度理解Go中try...catch...的panic、defer、recover用法
文章通过实验代码演示了Go语言中如何使用panic、defer和recover函数来模拟try...catch...的异常处理机制,并详细解释了每个函数的作用和在异常处理中的使用场景。
24 0
|
4月前
|
Go 开发者
Golang深入浅出之-Go语言 defer、panic、recover:异常处理机制
Go语言中的`defer`、`panic`和`recover`提供了一套独特的异常处理方式。`defer`用于延迟函数调用,在返回前执行,常用于资源释放。它遵循后进先出原则。`panic`触发运行时错误,中断函数执行,直到遇到`recover`或程序结束。`recover`在`defer`中捕获`panic`,恢复程序执行。注意避免滥用`defer`影响性能,不应对可处理错误随意使用`panic`,且`recover`不能跨goroutine捕获panic。理解并恰当使用这些机制能提高代码健壮性和稳定性。
80 2
|
4月前
|
Java Go 区块链
【Go语言专栏】Go语言中的延迟执行与defer语句
【4月更文挑战第30天】Go语言的延迟执行与defer语句用于资源释放和错误处理。defer通过关键字定义,函数返回时执行,顺序与定义相反。参数在定义时求值。应用包括资源释放、错误处理、成对操作和函数包装,是Go编程的关键特性。
40 0
|
4月前
|
网络协议 BI Go
Go-异常处理(defer recover panic)
Go-异常处理(defer recover panic)
60 0
|
9月前
|
Go
go defer用法_类似与python_java_finially
go defer用法_类似与python_java_finially
56 0
|
10天前
|
程序员 Go PHP
为什么大部分的 PHP 程序员转不了 Go 语言?
【9月更文挑战第8天】大部分 PHP 程序员难以转向 Go 语言,主要因为:一、编程习惯与思维方式差异,如语法风格和编程范式;二、学习成本高,需掌握新知识体系且面临项目压力;三、职业发展考量,现有技能价值及市场需求不确定性。学习新语言虽有挑战,但对拓宽职业道路至关重要。
40 10