为何Go函数foo中变量x在作用域结束后仍递增?
为什么foo函数里的x不会每次调用都重置为0?
哈哈,这个问题其实是Go里闭包特性的经典案例!咱们一步步拆解清楚:
首先看foo()函数的逻辑:它声明了一个局部变量x,然后返回一个匿名函数。这里的核心是——这个匿名函数是闭包,它捕获的是x的引用,而不是x的副本。
当你在main里执行a := foo()时,foo()确实执行完了,但它返回的闭包a还牢牢握着对x的引用!Go的垃圾回收器不会回收还被引用的变量,所以x并没有被销毁,而是一直留在内存里。
接下来每次调用a(),都是在对同一个x做x++操作:
- 第一次调用
a():x从0变成1,返回1 - 第二次调用
a():x从1变成2,返回2 - 第三次调用
a():x从2变成3,返回3
那如果想让每次调用都重置x怎么办?很简单,要是每次都调用foo()再执行返回的函数,每个闭包都会拥有自己独立的x:
func main() { fmt.Printf("%d\n", foo()()) // 输出1 fmt.Printf("%d\n", foo()()) // 输出1 fmt.Printf("%d\n", foo()()) // 输出1 }
因为每次调用foo()都会创建一个新的x变量,每个闭包捕获的都是自己专属的x引用,自然不会互相影响。
总结下关键点:
- 闭包不是复制外层变量的值,而是持有变量的引用
- 只要闭包还能被访问到,被它捕获的外层变量就不会被销毁
- 你只调用了一次
foo(),所以所有a()的调用都在操作同一个x
内容的提问来源于stack exchange,提问作者M A D H U R
相关产品推荐
相关产品推荐

