

新闻资讯
技术学院闭包捕获的是变量本身而非值,Go中闭包通过指针访问外层变量,导致多个闭包共享同一内存地址;循环中创建闭包时若未正确处理,易因变量被覆盖而引发意外行为。
Go 闭包访问外层变量时,拿的是变量的内存地址,相当于隐式持有了指针。哪怕你没写 *p 或 &x,只要闭包里读或写了那个变量,Go 就会把它“逃逸”到堆上,并让闭包结构体保存指向它的指针。所以多个闭包可能共享同一块内存 —— 改一个,另一个读到的就是新值。
常见错误写法:
for i := 0; i go func() { fmt.Println(i) }()
}
输出往往是 3 3 3,因为所有闭包都捕获了同一个变量 i 的地址,等 goroutine 真正执行时,循环早已结束,i 已是 3。解决办法不是加指针,而是让每次迭代绑定独立副本:
如果你在外层定义了一个指针 p := &x,再在闭包里用 *p,那闭包捕获的是 p 这个指针变量本身(地址),不是 x。这意味着:
每个闭包在运行时都是一个结构体:funcval + *capture。其中 *capture 指向一块堆内存,里面按顺序存着所有被捕获变量的值(或它们的地址)。访问时靠固定偏移直接取,没有多层解引用。所以
Go 闭包高效,但也意味着:你看到的“变量”,背后大概率已是堆上某个地址的别名。