defer关键词介绍

  • defer表示函数在执行之后结束之前触发的一个机制
  • 当执行函数时遇到defer关键字时首先将defer所绑定的操作放入栈中,当函数内全部执行完成之后再依次从栈中取出defer关键字绑定的操作来执行。

    defer的特性

    函数中只存在单个derfer

例如:

package main

import "fmt"

func main() {
    // 写入defer关键字
    defer fmt.Println("main函数执行结束")

    fmt.Println("main hello1")
    fmt.Println("main hello2")
}

运行结果:
image.png
可以看到当只存在一个derfer时,在执行完函数的全部语句才会执行defer后面制定的语句或者函数。

函数中存在多个derfer

多个derfer执行顺序是一种压栈的形式,在最前面的derfer先入栈,后面的defer后入栈,之后在调用时排在后面的defer先出栈执行,排在前面的defer后出栈执行。

例如:

package main

import "fmt"

func main() {
    // 写入defer关键字
    defer fmt.Println("main函数执行结束1")
    defer fmt.Println("main函数执行结束2")
    

    fmt.Println("main hello1")
    fmt.Println("main hello2")
}
  • 7、8行defer关键字,按照栈的规则,应该先运行第8行,再运行第7行

运行结果:
image.png

defer的压栈执行顺序

package main

import "fmt"

func func1() {
    fmt.Println("A")
}

func func2() {
    fmt.Println("B")
}
func func3() {
    fmt.Println("C")
}

func main() {
    defer func1()
    defer func2()
    defer func3()
}

执行结果:
image.png

根据defer关键字的性质,先将defer绑定的指令让如栈中,然后函数执行完成之后,将栈中defer绑定的指令依次取出执行,执行函数的顺序应该为func3func2func1

defer和return谁先谁后

用一个实现来判断一下defer和return谁先执行。

package main

import "fmt"

func deferFunc() int {
    fmt.Println("defer func 执行")
    return 0
}

func returnFunc() int {
    fmt.Println("return func 执行")
    return 0
}

func returnAndDefer() int {
    defer deferFunc()
    return returnFunc()
}

func main() {
    returnAndDefer()
}

运行结果:
image.png
从运行结果可以看出:当一个函数中既有return也有defer时(虽然情况比较少见),首先执行return,然后再执行defer。

理解起来就是defer就是在当前函数的声明周期执行结束之后才触发,而return属于函数执行周期的末尾,当return执行结束之后才会调用defer。

最后修改:2024 年 03 月 13 日
如果觉得我的文章对你有用,请随意赞赏