一尘不染

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

go

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

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.

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


阅读 206

收藏
2020-07-02

共1个答案

一尘不染

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

2020-07-02