如何golang的“延迟”捕获闭包的参数? [英] How golang's "defer" capture closure's parameter?

查看:271
本文介绍了如何golang的“延迟”捕获闭包的参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的代码(运行):

  package main 

importfmt

func main(){
var whatever [5] struct {}

for i:= range whatever {
fmt.Println(i)
} // part 1

for i:任何{
defer func(){fmt.Println(i)}()
} // part 2

for i:= range whatever {
defer func (n int){fmt.Println(n)}(i)
} // part 3
}

输出:



0
1
2
3
4
4
3
2
1
0
4
4
4
4
4



问题:第2部分和第2部分之间有什么区别?第3部分?为什么第2部分输出44444而不是43210?

解决方案

。当闭包(稍后)中的代码执行时,变量'i'具有它在范围语句的最后一次迭代中具有的值,即。 '4'。因此

  4 4 4 4 4 

部分输出。



part 3在其闭包中不捕获任何外部变量。由于规格说:


每次执行defer语句时,调用的函数值和参数都会照常进行计算,并重新保存,但实际的函数不会被调用。


因此,每个被拒绝的函数调用都有一个不同的'n'参数值。它是在执行defer语句的时候'i'变量的值。因此

  4 3 2 1 0 

部分输出,因为:


...延迟调用在LIFO命令之前立即执行周围函数返回...







要注意的关键是, defer语句执行时,不会执行'defer f()'中的f()'。



/ p>

当defer语句执行时,在'defer f(e)'中表达式'e'。


Here is my code (run):

package main

import "fmt"

func main() {
    var whatever [5]struct{}

    for i := range whatever {
        fmt.Println(i)
    } // part 1

    for i := range whatever {
        defer func() { fmt.Println(i) }()
    } // part 2

    for i := range whatever {
        defer func(n int) { fmt.Println(n) }(i)
    } // part 3
}

Output:

0 1 2 3 4 4 3 2 1 0 4 4 4 4 4

Question: What's the difference between part 2 & part 3? Why part 2 output "44444" instead of "43210"?

解决方案

The 'part 2' closure captures the variable 'i'. When the code in the closure (later) executes, the variable 'i' has the value which it had in the last iteration of the range statement, ie. '4'. Hence the

4 4 4 4 4

part of the output.

The 'part 3' doesn't capture any outer variables in its closure. As the specs say:

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 is not invoked.

So each of the defered function calls has a different value of the 'n' parameter. It is the value of the 'i' variable in the moment the defer statement was executed. Hence the

4 3 2 1 0

part of the output because:

... deferred calls are executed in LIFO order immediately before the surrounding function returns ...


The key point to note is that the 'f()' in 'defer f()' is not executed when the defer statement executes

but

the expression 'e' in 'defer f(e)' is evaluated when the defer statement executes.

这篇关于如何golang的“延迟”捕获闭包的参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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