• 设为首页
  • 收藏本站
  • 积分充值
  • VIP赞助
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    福建二哥 门户 查看主题

    go语言for循环中嵌套defer的执行顺序

    发布者: 晋3555 | 发布时间: 2025-8-14 08:44| 查看数: 51| 评论数: 0|帖子模式

    在Go语言中,
    1. defer
    复制代码
    语句用于延迟函数调用的执行,直到包含它的函数返回时才执行。当
    1. defer
    复制代码
    语句嵌套在
    1. for
    复制代码
    循环中时,它的执行时机仍然遵循
    1. defer
    复制代码
    的基本规则,但需要注意循环和函数返回的上下文。

    基本规则


    • 延迟执行
      1. defer
      复制代码
      语句会在包含它的函数返回时执行,无论函数是正常返回还是因为错误、panic等情况返回。
    • 后进先出(LIFO):如果有多个
      1. defer
      复制代码
      语句,它们会按照后进先出的顺序执行。

    在for循环中使用defer

    1. defer
    复制代码
    语句嵌套在
    1. for
    复制代码
    循环中时,它的执行时机与循环的上下文有关:

    1. 循环体内的defer

    如果
    1. defer
    复制代码
    语句位于
    1. for
    复制代码
    循环体内部,它会在每次循环迭代结束时被记录下来,但实际执行时机取决于循环所在的函数何时返回。

    2. 函数返回时执行

    无论循环执行了多少次,
    1. defer
    复制代码
    语句都会在包含它的函数返回时按照记录的顺序执行。
    示例代码
    以下是一个示例代码,帮助理解
    1. defer
    复制代码
    1. for
    复制代码
    循环中的行为:
    1. package main

    2. import "fmt"

    3. func main() {
    4.     for i := 0; i < 3; i++ {
    5.         defer fmt.Println("Deferred in loop iteration:", i)
    6.     }
    7.     fmt.Println("Loop finished")
    8. }
    复制代码
    输出结果:
    1. Loop finishedDeferred in loop iteration: 2Deferred in loop iteration: 1Deferred in loop iteration: 0
    复制代码
    解释:

    • 循环体内的
      1. defer
      复制代码
      语句会在每次迭代结束时被记录下来。
    • 循环结束后,程序继续执行,直到
      1. main
      复制代码
      函数返回。
      1. main
      复制代码
      函数返回时,
      1. defer
      复制代码
      语句按照后进先出的顺序执行,即先执行最后一次迭代的
      1. defer
      复制代码
      ,再执行前一次的,以此类推。
    注意事项

    • 性能问题:在循环中频繁使用
      1. defer
      复制代码
      可能会导致性能问题,因为每次迭代都会记录一个延迟调用。
    • 变量捕获:如果
      1. defer
      复制代码
      语句捕获了循环变量(如
      1. i
      复制代码
      ),可能会导致意外的行为。例如,如果
      1. defer
      复制代码
      捕获的是变量的引用,而不是值,可能会导致所有
      1. defer
      复制代码
      语句打印相同的值。
    如果在
    1. for
    复制代码
    循环中嵌套的
    1. defer
    复制代码
    调用是一个函数,而不是直接打印值,输出结果可能会因为函数的实现而有所不同。特别是,如果函数内部对变量进行了捕获(如循环变量
    1. i
    复制代码
    ),可能会导致一些意外的行为。

    示例 1:defer 调用一个函数,捕获循环变量的值

    如果函数捕获的是循环变量的值(通过参数传递),那么每次调用
    1. defer
    复制代码
    时都会记录当前迭代的值。这种情况下,输出结果与直接打印值类似。
    1. package main

    2. import "fmt"

    3. func printDeferred(value int) {
    4.     fmt.Println("Deferred value:", value)
    5. }

    6. func main() {
    7.     for i := 0; i < 3; i++ {
    8.         defer printDeferred(i)
    9.     }
    10.     fmt.Println("Loop finished")
    11. }
    复制代码
    输出结果:
    1. Loop finishedDeferred value: 2Deferred value: 1Deferred value: 0
    复制代码
    解释:

    • 每次迭代时,
      1. defer
      复制代码
      调用了
      1. printDeferred
      复制代码
      函数,并将当前的
      1. i
      复制代码
      作为参数传递给函数。
    • 函数捕获的是变量的值,因此每次迭代都会记录当前迭代的值。
    • 函数返回时,
      1. defer
      复制代码
      按照后进先出的顺序执行。

    示例 2:defer 调用一个函数,捕获循环变量的引用

    如果函数捕获的是循环变量的引用(如直接使用变量
    1. i
    复制代码
    ,而不是通过参数传递值),那么所有
    1. defer
    复制代码
    调用的输出可能会相同,因为它们都引用了同一个变量。
    1. package main

    2. import "fmt"

    3. func printDeferred() {
    4.     fmt.Println("Deferred value:", i)
    5. }

    6. func main() {
    7.     for i := 0; i < 3; i++ {
    8.         defer printDeferred()
    9.     }
    10.     fmt.Println("Loop finished")
    11. }
    复制代码
    输出结果:
    1. Loop finishedDeferred value: 3Deferred value: 3Deferred value: 3
    复制代码
    解释:

      1. for
      复制代码
      循环中,
      1. defer
      复制代码
      调用了
      1. printDeferred
      复制代码
      函数,但没有传递参数。
    • 函数内部直接访问了变量
      1. i
      复制代码
      ,因此捕获的是变量的引用。
      1. defer
      复制代码
      执行时,循环已经结束,
      1. i
      复制代码
      的值为 3(循环结束后的值)。
    • 所有
      1. defer
      复制代码
      调用都打印了 3,因为它们引用的是同一个变量。

    示例 3:defer 调用一个函数,捕获循环变量的值(闭包)

    如果函数是一个闭包,捕获了循环变量的值,那么每次迭代都会捕获当前迭代的值。
    1. package main

    2. import "fmt"

    3. func main() {
    4.     for i := 0; i < 3; i++ {
    5.         defer func(value int) {
    6.             fmt.Println("Deferred value:", value)
    7.         }(i)
    8.     }
    9.     fmt.Println("Loop finished")
    10. }
    复制代码
    输出结果:
    1. Loop finishedDeferred value: 2Deferred value: 1Deferred value: 0
    复制代码
    解释:

    • 每次迭代时,
      1. defer
      复制代码
      调用了一个匿名函数,并将当前的
      1. i
      复制代码
      作为参数传递给闭包。
    • 闭包捕获的是变量的值,因此每次迭代都会记录当前迭代的值。
    • 函数返回时,
      1. defer
      复制代码
      按照后进先出的顺序执行。
    总结
    如果
    1. defer
    复制代码
    调用的是一个函数,输出结果会受到以下因素的影响:

    • 函数是否捕获变量的值或引用

      • 如果捕获的是值(通过参数传递),则每次迭代都会记录当前迭代的值。
      • 如果捕获的是引用(直接访问变量),则所有
        1. defer
        复制代码
        调用可能会打印相同的值(循环结束后的值)。

    • 闭包的使用:如果使用闭包捕获变量的值,每次迭代都会记录当前迭代的值。
    因此,使用
    1. defer
    复制代码
    时需要注意变量捕获的细节,以避免意外的行为。

    总结

    1. for
    复制代码
    循环中嵌套
    1. defer
    复制代码
    时,
    1. defer
    复制代码
    语句会在每次迭代结束时被记录,但实际执行时机是在包含它的函数返回时。理解
    1. defer
    复制代码
    的执行规则和上下文非常重要,以避免意外行为。
    到此这篇关于go语言for循环中嵌套defer的执行顺序的文章就介绍到这了,更多相关go语言defer的执行顺序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    来源:互联网
    免责声明:如果侵犯了您的权益,请联系站长(1277306191@qq.com),我们会及时删除侵权内容,谢谢合作!

    最新评论

    QQ Archiver 手机版 小黑屋 福建二哥 ( 闽ICP备2022004717号|闽公网安备35052402000345号 )

    Powered by Discuz! X3.5 © 2001-2023

    快速回复 返回顶部 返回列表