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

简介: defer在go中的作用就是延迟执行,一般常用来关闭一些io流等

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

defer的作用


defergo中的作用就是延迟执行,一般常用来关闭一些io流等。简单来个例子:

package main
import "fmt"
func main() {
  fmt.Println("1")
  defer func() {
    fmt.Println("2")
  }()
  fmt.Println("3")
}

上面的例子输出:

1
3
2

从上面得知defer会在程序结束前被执行,但是如果有多个defer呢?这时候go是执行的呢?

多个defer执行流程

go1.12版本中,defer对应的是一个结构体_defer。每个gogoroutine上都有一个指向这个结构体的指针*_defer。所有_defer通过结构体中的link组成一个链表。每添加一个_defer都会在链表头部上插入,所以就导致了先入后出现象。**所有的_defer**结构体都在堆内分配内存。

频繁的堆分配势必影响性能,所以Go语言会预分配不同规格的deferpool,执行时从空闲_defer中取一个出来用。没有空闲的或者没有大小合适的,再进行堆分配。用完以后,再放回空闲_defer池。这样可以避免频繁的堆分配与回收。

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

通过上面的流程,我们就可以理解多个defer的输出流程了

package main
import "fmt"
func main() {
  fmt.Println("1")
  defer func() {
    fmt.Println("2")
  }()
  defer func() {
    fmt.Println("3")
  }()
  defer func() {
    fmt.Println("4")
  }()
  fmt.Println("5")
}

输出:

1
5
4
3
2

defer的优化

上面说到每个defer都是由一个个结构组成的,所以go会对多个同样的没有捕获参数的defer做出优化。具体看图解

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

defer的参数取值

defer注册的时候,编译器会在它自己的个参数后面,开辟一段空间,用于存放defer函数的返回值和参数。这一段空间会在注册defer时,直接拷贝到_defer结构体的后面。

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

所以就可以解释下面这段代码了:

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

输出:

1


目录
相关文章
|
4月前
|
Go
Go语言中defer的执行顺序详解
【2月更文挑战第22天】
68 4
|
10月前
|
Cloud Native Go
GO 中的 defer 有哪些注意事项?上
GO 中的 defer 有哪些注意事项?上
|
1月前
|
存储 Go
掌握 Go 语言的 defer 关键字
掌握 Go 语言的 defer 关键字
|
13天前
|
Go
实验深度理解Go中try...catch...的panic、defer、recover用法
文章通过实验代码演示了Go语言中如何使用panic、defer和recover函数来模拟try...catch...的异常处理机制,并详细解释了每个函数的作用和在异常处理中的使用场景。
24 0
|
3月前
|
Go 开发者
GVM:Go语言版本和包管理的神器!
GVM,Go版本管理器,简化了在单机上切换不同Go版本的任务。
69 0
|
9月前
|
Dubbo 应用服务中间件 API
Go语言微服务框架重磅升级:dubbo-go v3.2.0 -alpha 版本预览
随着 Dubbo3 在云原生微服务方向的快速发展,Dubbo 的 go 语言实现迎来了 Dubbo3 版本以来最全面、最大幅度的一次升级,这次升级是全方位的,涉及 API、协议、流量管控、可观测能力等。
|
4月前
|
Go 开发者
Golang深入浅出之-Go语言 defer、panic、recover:异常处理机制
Go语言中的`defer`、`panic`和`recover`提供了一套独特的异常处理方式。`defer`用于延迟函数调用,在返回前执行,常用于资源释放。它遵循后进先出原则。`panic`触发运行时错误,中断函数执行,直到遇到`recover`或程序结束。`recover`在`defer`中捕获`panic`,恢复程序执行。注意避免滥用`defer`影响性能,不应对可处理错误随意使用`panic`,且`recover`不能跨goroutine捕获panic。理解并恰当使用这些机制能提高代码健壮性和稳定性。
77 2
|
4月前
|
Java Go 区块链
【Go语言专栏】Go语言中的延迟执行与defer语句
【4月更文挑战第30天】Go语言的延迟执行与defer语句用于资源释放和错误处理。defer通过关键字定义,函数返回时执行,顺序与定义相反。参数在定义时求值。应用包括资源释放、错误处理、成对操作和函数包装,是Go编程的关键特性。
38 0
|
4月前
|
网络协议 BI Go
Go-异常处理(defer recover panic)
Go-异常处理(defer recover panic)
59 0
|
9月前
|
Go
go defer用法_类似与python_java_finially
go defer用法_类似与python_java_finially
54 0