当前位置: 首页 > 面试题库 >

为什么在范围循环中延迟以相反的顺序调用?

罗晨
2023-03-14
问题内容

我遇到了一个有关“反向范围”的问题的答案],我打算对其投下反对票,因为它看起来很可笑,但经过检查就可以了(!):

https://play.golang.org/p/4K2fDlSoCm

package main

import (
    "fmt"
)

func main() {
    s := []int{1, 2, 3, 4, 5}
    for i, _ := range s {
        defer fmt.Println(s[i])
    }
}

输出为:

5
4
3
2
1
Program exited.

任何想法为什么它会这样工作?我是不是可以保证不能完全按照相反的顺序执行?另外我也不认为这是编写程序的好方法,但很想知道为什么我们会得到这个结果。


问题答案:

deferLIFO或堆栈-
保证以相反的顺序执行。它获取第一个defer,并将其放在某个内部堆栈中(可能我不知道血腥的细节),然后将下一个放在该堆栈的defer顶部,然后当它到达函数末尾时,展开,开始在顶部。它看起来像是在for-loop里做的(我知道这是Go的示例,而不是您的示例),但是在其他情况下,一个功能依赖于其他功能的清理,这更有意义,为什么它应该是IS,保证执行顺序相反。

这是一个不同的示例,都是伪代码,但希望这一点很清楚。

open stream1
defer close stream1
defer write stream1 "stream2 better be closed, or we are in trouble..."
open stream2
defer close stream2
defer stream2 "this is the last you'll ever hear from stream2"

connect stream2 to stream1

write stream2 "hey, we are in stream2, this feeds into stream1"

应该打印类似:

"hey, we are in stream2, this feeds into stream1"
"this is the last you'll ever hear from stream2"
"stream2 better be closed, or we are in trouble..."

如果您没有关于反向订购的保证,则不能确定stream1您在期间仍处于打开状态defer stream2 write



 类似资料:
  • 问题内容: 因此,我将顺序的ajax链接在一起,以按顺序加载URL数组。最初,我使用代替,并且无论哪种方式都可以正常工作- 只要所有网址都存在。但是,由于可能会丢失文件,因此我想对此进行补偿,然后,最后通知用户丢失了哪些文件,以便更轻松地进行纠正。 但是,问题是,在丢失的文件/ 404上,代码会像应执行的那样执行,但随后退出循环,从而阻止了进一步的ajax调用。因此,我认为,我需要某种方式来处理并

  • 我在试着理解为什么一些简单的环路会以这样的速度运行 第一种情况: 根据IACA,吞吐量是1个周期,瓶颈是端口1,05。我不明白为什么它是1 cylce。毕竟我们有两个循环承载的依赖关系: 而且这种Latency是循环进行的,所以它应该会减慢我们的迭代。 第二种情况: 我更不明白为什么吞吐量是1.65。

  • 问题内容: 我想在循环内添加延迟/睡眠: 我这样尝试过: 只有第一种情况是正确的:显示后,它将等待3秒钟,然后显示,但随后将不断重复。 我想要的是在显示3秒之后显示出来,然后它需要第二次等待3秒,依此类推。 问题答案: 该函数是非阻塞的,将立即返回。因此,您的循环将非常快速地迭代,并且将快速连续地发起3秒超时触发。这就是为什么您的第一个警报会在3秒钟后弹出,而其余所有警报都将连续不断地出现。 您可

  • 问题内容: 在Java中,循环的主体和循环条件不属于同一范围。因此,以下代码将无法编译: 但是这段代码对我来说确实有意义。 另外,如果身体和身体状况都在同一范围内,我将找不到任何陷阱。由于主体将始终被执行,而Java则不会,我不知道如何跳过最外层主体范围中的变量声明。即使有可能,编译器始终可以检测到这种可能性,然后产生编译时错误。 是否有这种现象的原因(除了将循环的格式保持为与相同)?我真的很好奇

  • 问题内容: 我需要在循环中对数据库进行SQL查询: 更好的方法是:保持原样或循环后移动: 或者是其他东西 ? 问题答案: 整个要点是直到函数返回才执行,因此将其放置在要关闭的资源打开后的适当位置。但是,由于要在循环内创建资源,因此根本不要使用defer- 否则,在函数退出之前,您不会关闭在循环内创建的任何资源,因此它们会堆积直到然后。相反,您应该在每次循环迭代结束时关闭它们, 而无需 :

  • 问题内容: 我有一个LinkedHashMap: 我需要从给定键的位置向后迭代。因此,如果为我提供了第十个项目的密钥,则需要向后迭代哈希表9、8、7等。 问题答案: 您不必遍历它。但是拔下钥匙并将其存储在列表中会很方便。这就是执行indexOf()类型操作的唯一方法。