提问人:snath03 提问时间:8/6/2022 更新时间:8/6/2022 访问量:123
当函数作为函数的参数给出时,它是按值传递还是按指针传递 [closed]
When a function is given as an argument to a function, is it pass-by-value or pass-by-pointer [closed]
问:
举个例子——
func funcB() { fmt.Println("Hi") })
funcA(funcB)
是否接收指向 ?或者它是否正在接收一个成熟的不可变函数?funcA
funcB
所以,如果我执行这段代码——
func funcA() { fmt.Println("Hi") })
funcB(funcA)
funcC(funcA)
funcD(funcA)
funcE(funcA)
funcF(funcA)
是所有函数调用都在创建一个新对象,还是所有函数调用都接收指向 的相同指针?funcA
funcA
答:
函数不包含要通过值或引用传递的状态,即它们只是可执行代码。当您将一个函数传递给另一个函数时,您正在引用函数主体的可执行代码。
匿名函数怎么样?
还可以将匿名函数或闭包存储到值中。在这种情况下,您的问题变得更加有趣,因为闭包可以保持状态。func()
闭包是通过值还是通过引用传递给函数?
func call(f func()) {
f()
}
func main() {
var i int
f := func() {
fmt.Println(i)
i++
}
call(f)
call(f)
}
运行上述代码输出:
0
1
我们可以得出结论,闭包的状态(即捕获的变量)在调用 之间以某种方式共享。原则上,这种行为可以通过以下方式实现:i
call()
- 闭包通过引用捕获其环境,并按值或引用传递。
- 闭包按值捕获其环境,并且仅通过引用传递。
为了了解闭包如何捕获其环境,我们可以更改 in 的值,并查看闭包看到的值是否受到影响。如果我们将下面的代码附加到:i
main()
i
main()
i = 100
call(f)
然后,显示。因此,在 和 之间共享 和 闭包(即,闭包没有自己的 副本)。因此,闭包通过引用来捕获其环境(我们现在可以排除上面的 2. 选项)。100
i
main()
i
在这一点上,我们仍然没有发现闭包是按值传递还是按引用传递。但是,我们已经知道,闭包的捕获状态实际上是通过引用函数传递的,因为闭包包含对捕获状态的引用。这很可能是最关键的见解。
即便如此,我们还是可以看到闭包是按值传递的:
func change(f func()) {
f = func() {
fmt.Println("replaced")
}
}
func main() {
f := func() {
fmt.Println("original")
}
change(f)
f() // prints "original"
}
结论
函数只是代码。它们不存储状态。函数是某些可执行代码的内存地址。当您将一个函数传递给另一个函数时,您正在提供此地址。
匿名函数或闭包可以保存与封闭环境相对应的状态。即使闭包是按值传递的,它们所持有的状态也是对它们捕获的环境的引用。因此,最终效果是闭包捕获的环境通过引用传递。
评论
func mutateFunction(f func(int)int) { f = nil }; f := func (i int) int { return i * 2}; mutateFunction(f); fmt.Println(f(2));