一尘不染

Golang延迟行为

go

关于延期,Effective
Go
声明以下内容:

延迟函数(如果函数是方法,则包括接收方)的参数在 延迟 执行时而不是在 调用
执行时进行评估。除了避免担心函数执行时变量会更改值外,这还意味着单个延迟的调用站点可以延迟多个函数的执行。这是一个愚蠢的例子。

for i := 0; i < 5; i++ {
    defer fmt.Printf("%d ", i)
}

延迟函数以LIFO顺序执行,因此该4 3 2 1 0函数返回时将导致打印此代码。

这个例子使我感到困惑。如果在执行defer调用时评估了参数,则应该打印for循环中的延迟器,5 5 5 5 5因为将在for循环结束时调用这些延迟器,届时i将为5。在for循环结束时评估延迟器将因此,所有通话结果为5。

我在这里想念什么吗?


阅读 517

收藏
2020-07-02

共1个答案

一尘不染

这似乎是连贯的(另请参阅“ 延迟,恐慌和恢复 ”)

周围函数返回 后, 将按照 后进 先出的顺序执行延迟的函数调用。

该函数打印“ 3210”:

func b() {
    for i := 0; i < 4; i++ {
        defer fmt.Print(i)
    }
}

defer评估时的最后一次调用意味着i=3,最后一个意味着最后一个i=2,依此类推。

Golang规格

每次defer执行“ ”语句时,都会照常评估调用的函数值和参数并重新保存,但实际的函数体不会执行。


defers将被称为FUNC结束时

是的,但是在循环运行时会先评估它们的参数。

当与闭包(函数文字)一起使用时,“
如何golang的“延迟”捕获闭包的参数?”中有一个比较棘手的defer案例,如“为什么在Golang中闭包主体后面添加“”中所详细说明”。()

2020-07-02