本文介绍了Golang延迟行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有效的 Go声明以下关于延迟:

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

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

延迟函数按后进先出的顺序执行,所以这段代码会导致函数返回时打印4 3 2 1 0.

这个例子让我很困惑.如果在执行 defer 调用时评估参数,那么 for 循环中的 defers 应该打印 5 5 5 5 5 因为 defers 将在 for 循环结束时被调用,并且在那个时候 i 将是 5.因此,在 for 循环结束时评估 defers 将导致所有调用为 5.

我在这里遗漏了什么吗?

解决方案

这看起来很连贯(另见推迟、恐慌和恢复")

延迟的函数调用以后进先出的顺序执行在周围函数返回之后.

该函数打印3210":

func b() {对于我:= 0;我<4;我++ {延迟 fmt.Print(i)}}

评估 defer 时的最后一次调用表示 i=3,前一个到最后一个表示 i=2,依此类推.

Golang 规范:

每次执行defer"语句时,函数值和调用的参数都会像往常一样评估并重新保存,但不会执行实际的函数体.

defers 将在 func 结束时调用

是的,但它们的参数是在循环运行时之前评估的.

golang 的defer"如何捕获闭包的参数?"与闭包一起使用时,您有一个更棘手的 defer 案例 (函数字面量),详见为什么在 Golang 中的闭包体之后添加()"?".

Effective Gostates the following regarding defer:

This example confuses me. If parameters are evaluated when the defer call is executed, then the defers in the for loop should print 5 5 5 5 5 since the defers will be called when the for loop ends, and at that time i would be 5. Evaluating defers at the end of the for loop will thus result in 5 for all calls.

Am I missing something here?

解决方案

That seems coherent (see also "Defer, Panic, and Recover")

Deferred function calls are executed in Last In First Out order after the surrounding function returns.

This function prints "3210":

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

The last call when the defer is evaluated means i=3, the previous to last means i=2 and so on.

Golang spec:


yes, but their arguments are evaluated before, while the loop is running.

You have a trickier defer case in "How golang's "defer" capture closure's parameter?" when used with closure (function literal), as detailed in "Why add "()" after closure body in Golang?".

这篇关于Golang延迟行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-03 11:07