Golang推迟行为 [英] Golang defer behavior

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

问题描述

Effective Go
声明以下有关延期:


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

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

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


这个例子令我困惑。如果在执行延迟调用时评估参数,那么for循环中的延迟应该会打印 5 5 5 5 5 ,因为当for循环结束时会调用延迟,那么当时 i 就会是5.评估for循环结束时的延迟因此将导致所有调用的结果都为5.



我在这里丢失了什么吗?

//blog.golang.org/defer-panic-and-recoverrel =noreferrer>延迟,恐慌和恢复)

推迟函数调用以周围函数返回后的后进先出顺序执行。



此函数打印3210:

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

defer 被评估时的最后一次调用意味着 i = 3 ,前一个意思是 i = 2 等等。



Golang规范


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







defers 将在func结束时被调用


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



golang的推迟捕获封锁参数?与闭包一起使用时(函数文字),详见为什么要在Golang中关闭正文之后添加()

Effective Go states the following regarding defer:

The arguments to the deferred function (which include the receiver if the function is a method) are evaluated when the defer executes, not when the call executes. Besides avoiding worries about variables changing values as the function executes, this means that a single deferred call site can defer multiple function executions. Here's a silly example.

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

Deferred functions are executed in LIFO order, so this code will cause 4 3 2 1 0 to be printed when the function returns.

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:

Each time the "defer" statement executes, the function value and parameters to the call are evaluated as usual and saved anew but the actual function body is not executed.


the defers will be called when func ends

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推迟行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆