Golang-Defer

简介: Golang-Defer

defer触发时机


A “defer” statement invokes a function whose execution is deferred to the moment the surrounding function returns, either because the surrounding function executed a return statement, reached the end of its function body, or because the corresponding goroutine is panicking.


Go官方文档中对defer的执行时机做了阐述,分别是。


  • 包裹defer的函数返回时


  • 包裹defer的函数执行到末尾时


  • 所在的goroutine发生panic时


defer执行顺序


当一个方法中有多个defer时, defer会将要延迟执行的方法“压栈”,当defer被触发时,将所有“压栈”的方法“出栈”并执行。所以defer的执行顺序是LIFO的。


执行顺序如下


# 常规执行语句1 -> 语句2 -> 语句3 -> 语句4# 在语句2,语句3中添加defer后执行顺序如下语句1 -> 语句4 -> 语句3(带defer) -> 语句2(带defer)


defer示例


package mainimport "fmt"func main() {
    d()
}func d() {
    fmt.Print("start" + "  ")
    fmt.Print("processing1" + "  ")
    fmt.Print("processing2" + "  ")
    fmt.Print("end" + "  ")
}


  • 没有defer:


start  -> processing1  ->  processing2  -> end


  • processing1、processing2 加入defer:


start  -> end  -> processing2  -> processing1


defer使用规则


defer会实时解析参数


package mainimport "fmt"func main() {
    i := 0
    defer fmt.Println(i)
    i ++    return}// 0


这是因为虽然我们在defer后面定义的是一个带变量的函数: fmt.Println(i). 但这个变量(i)在defer被声明的时候,就已经确定其确定的值了


defer的类栈执行


栈:先入后出


package mainimport "fmt"func f1()  {
    fmt.Println(1)
}func f2()  {
    fmt.Println(2)
}func main() {    defer f1()
    f2()
}// 2\1


defer可以读取有名返回值


func c() (i int) {   defer func() { i++ }()   return 1}func main()  {
   fmt.Println(c())
}// 2


在开头的时候,我们说过defer是在return调用之后才执行的。这里需要明确的是defer代码块的作用域仍然在函数之内,结合上面的函数也就是说,defer的作用域仍然在c函数之内。因此defer仍然可以读取c函数内的变量(如果无法读取函数内变量,那又如何进行变量清除呢…)。


当执行return 1 之后,i的值就是1. 此时此刻,defer代码块开始执行,对i进行自增操作。因此输出2.

目录
相关文章
|
5月前
|
人工智能 数据库连接 Go
golang defer 详解
golang defer 详解
54 0
|
安全 Go
Golang 语言中的 defer 怎么使用?
Golang 语言中的 defer 怎么使用?
53 0
|
8月前
|
Java Go
浅谈Golang 不同版本的defer
浅谈Golang 不同版本的defer
63 1
|
8月前
|
存储 编译器 测试技术
Golang底层原理剖析之defer
Golang底层原理剖析之defer
85 0
|
存储 Java 编译器
Golang中的defer(2)
Golang中的defer(2)
4728 2
|
编译器 Go
Golang中的defer
Golang中的defer
67 0
|
存储 编译器 Go
Go的defer
在Go语言中,defer是一个关键字,用于延迟执行函数或方法的调用。当使用defer关键字时,被延迟执行的函数或方法会在包含它的函数返回之前被调用。
62 0
|
Go
Golang中的defer(1)
Golang中的defer(1)
83 0
Golang中函数的使用
Golang中函数的使用
86 0