Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go闭包捕获规则与延迟捕获规则有何不同?_Go - Fatal编程技术网

Go闭包捕获规则与延迟捕获规则有何不同?

Go闭包捕获规则与延迟捕获规则有何不同?,go,Go,下面的Go代码演示了延迟闭包和Go闭包之间的闭包捕获规则的区别。在一个教程中,我被告知for循环变量的作用域仅限于循环体,但这里似乎有所不同 package main import "fmt" func deferred() { for i := 0; i < 5; i++ { defer fmt.Println(i) } } func cps() { clo := new(func()) *clo = func() {} de

下面的Go代码演示了延迟闭包和Go闭包之间的闭包捕获规则的区别。在一个教程中,我被告知for循环变量的作用域仅限于循环体,但这里似乎有所不同

package main

import "fmt"

func deferred() {
    for i := 0; i < 5; i++ {
        defer fmt.Println(i)
    }
}

func cps() {
    clo := new(func())
    *clo = func() {}
    defer func() { (*clo)() }()
    for i := 0; i < 5; i++ {
        oldClo := *clo
        *clo = func() {
            fmt.Println(i)
            oldClo()
        }
    }
}

func cpsCpy() {
    clo := new(func())
    *clo = func() {}
    defer func() { (*clo)() }()
    for i := 0; i < 5; i++ {
        oldClo := *clo
        cpy := i
        *clo = func() {
            fmt.Println(cpy)
            oldClo()
        }
    }
}

func main() {
    fmt.Println("defer")
    deferred()
    fmt.Println("cps")
    cps()
    fmt.Println("cpsCpy")
    cpsCpy()
}
如果差异是有意造成的,那么有哪些不同的用例可以证明这一点?

这一点很清楚。对于任何关心变量捕获规则之类的东西的人来说,该规范通常都是至关重要的读物,相对而言,它的内容相对较短。这里说的是:

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

它也包括在

总是很难让每个人都满意地证明设计决策的合理性,尤其是
延迟
的设计决策有时会让人们感到惊讶,特别是当您执行
延迟f1(f2(x))
并忘记
f2(x)
时,将立即进行评估

不过,有一件事可能有助于记住它,那就是
defer
(或
go
)之后的是函数调用,而只是函数调用本身(甚至不是参数的计算)会随着时间的推移而改变。闭包定义了一个代码块,在执行代码时访问变量


由于您对闭包中获取的变量捕获类型的用途感到好奇,因此,如果您将闭包与类似于
ForEach
的方法一起使用,这是一个很有用的示例:

myBTree.ForEach(func (key, value []byte) {
    //...
})
如果像在常规的
for
循环中一样,大括号之间的代码可以修改外部范围中的变量,那就很好了。这要求闭包访问变量,而不仅仅是特定时间的变量值。

这一点很清楚。对于任何关心变量捕获规则之类的东西的人来说,该规范通常都是至关重要的读物,相对而言,它的内容相对较短。这里说的是:

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

它也包括在

总是很难让每个人都满意地证明设计决策的合理性,尤其是
延迟
的设计决策有时会让人们感到惊讶,特别是当您执行
延迟f1(f2(x))
并忘记
f2(x)
时,将立即进行评估

不过,有一件事可能有助于记住它,那就是
defer
(或
go
)之后的是函数调用,而只是函数调用本身(甚至不是参数的计算)会随着时间的推移而改变。闭包定义了一个代码块,在执行代码时访问变量


由于您对闭包中获取的变量捕获类型的用途感到好奇,因此,如果您将闭包与类似于
ForEach
的方法一起使用,这是一个很有用的示例:

myBTree.ForEach(func (key, value []byte) {
    //...
})


如果像在常规的
for
循环中一样,大括号之间的代码可以修改外部范围中的变量,那就很好了。这要求闭包访问变量,而不仅仅是特定时间的变量值。

没有区别,您可以看到:@JimB好吧,FAQ让它看起来像一个for循环创建了两个作用域,一个用于迭代器,一个用于主体内部。但是,延迟似乎还是不同的:它并没有创建一个闭包(正如我认为有些地方所宣称的那样)。它首先对非引用变量执行一个奇怪的基于值的捕获,然后进行闭包,不,不,范围在所有情况下都是相同的。在
cps
中,您只需捕获单个
i
变量并将其打印5次。@JimB恐怕我还是有点困惑。您是否可以写一个答案,或者将for扩展为一个go“while”循环,以演示作用域到底是什么?为什么不延迟捕获单个i变量呢?是的,@JimB正确地认为闭包的行为是指定的。延迟所做的根本不是变量捕获;它被指定评估函数参数并保存它们。没有区别,您可以看到:@JimB好吧,FAQ让它看起来像是一个for循环创建了两个作用域,一个用于迭代器,一个用于主体内部。但是,延迟似乎还是不同的:它并没有创建一个闭包(正如我认为有些地方所宣称的那样)。它首先对非引用变量执行一个奇怪的基于值的捕获,然后进行闭包,不,不,范围在所有情况下都是相同的。在
cps
中,您只需捕获单个
i
变量并将其打印5次。@JimB恐怕我还是有点困惑。您是否可以写一个答案,或者将for扩展为一个go“while”循环,以演示作用域到底是什么?为什么不延迟捕获单个i变量呢?是的,@JimB正确地认为闭包的行为是指定的。延迟所做的根本不是变量捕获;它被指定对函数args求值并保存它们。好的,所以defer不会创建闭包,它是一个完整的独立语句,它有自己的行为,需要单独关注。在我看来,这里不合理的决定是闭包捕获引用(而不是使用参数,如值捕获,引用类型除外);这看起来就像是一种容易出错的方法,它可以帮助那些想让这种行为发生的人避免写额外的一行创建指针。因此,感谢您回答我问题的第一部分。请你回答第二个问题好吗?我不需要被说服,但就我自己的知识而言,我希望看到引用捕获对我有什么帮助。@VF1:defer并不是很特别,只是函数参数总是在调用点求值。如果你推迟闭包,效果也是一样的:@JimB好吧,你是说它不特别,但是