我遇到关于#34;反向范围"的问题的answer。而我本来打算投票,因为它看起来很荒谬,但经过检查,确实有效(!):
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.
为什么它以这种方式运作的任何想法?我是对的吗?不保证完全以相反的顺序执行?此外,我不认为这是编写程序的好方法,但很想知道为什么我们会得到这个结果。
答案 0 :(得分:9)
defer
是LIFO
或堆栈 - 保证以相反的顺序执行。它得到第一个defer
并将其放在一些内部堆栈上(可能,我不知道血淋淋的细节),然后将下一个defer
放在那个上面,然后当它击中了函数的末尾,它从顶部开始展开。它似乎是在for
循环中设计的(我知道这是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
仍处于打开状态。