You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言闭包持有环境范围与变量未被GC回收的疑问

Go闭包中指针指向变量未被回收的原因

问题描述

我参照线上闭包教程编写了如下代码:

func foo1() func() {
    xValue := 1
    x := &xValue
    defer func() {
        xValue = 2
    }()
    return func() {
        *x = *x + 1
        fmt.Printf("foo1 val = %d\n", *x)
    }
}

func main() {
    f1 := foo1()
    f1()
    f1()
    f1()
}

执行f1 := foo1()后,我认为变量xValue应该被回收,使用*x会出现错误,但代码运行正常,输出结果为:

foo1 val = 3
foo1 val = 4
foo1 val = 5

我想了解是闭包除指针本身外还持有指针指向的值,还是Go语言的垃圾回收机制导致xValue未被回收?

解答

这其实是Go的闭包捕获规则和垃圾回收机制共同作用的结果:

  • 闭包会捕获它用到的所有变量,哪怕是通过指针间接引用的底层值。你代码里返回的匿名函数用到了指针x,而x指向xValue,Go编译器能识别到xValue被闭包间接关联了,所以foo1执行完后不会立刻回收xValue的内存。
  • 再捋一遍执行流程:调用foo1时,先把xValue设为1,x指向它;然后defer的函数会在foo1返回前执行,把xValue改成2;最后返回的闭包攥着对x的引用,只要f1还在,x指向的xValue就会被GC判定为“还在被使用”,不会被回收。
  • 每次调用f1(),都会给*x(也就是xValue)加1,所以第一次调用是2+1=3,之后每次加1,就有了你看到的输出结果。

总结一下:闭包通过指针间接引用了xValue,Go的GC会跟踪这种引用关系,只要闭包还存在,xValue就会一直留在内存里,不会被回收。

内容的提问来源于stack exchange,提问作者Shuaike Jiang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 19:10:31