怪奇物语

怪奇物语

首页 新随笔 联系 管理

golang Go 闭包与循环变量陷阱及解决方案


示例 1:未处理的闭包变量陷阱

func main() {
    for i := 0; i < 3; i++ {
        defer func() { println(i) }()
    }
}

现象

输出:3 3 3(三个 3

原因

  • 闭包捕获的是变量的引用,而非值。
  • 循环结束后,i 的最终值为 3,所有 defer 的匿名函数捕获的都是同一个外部变量 i,因此打印的都是 3

示例 2:通过局部变量解决陷阱

func main() {
    for i := 0; i < 3; i++ {
        i := i // 定义循环体内局部变量 i
        defer func() { println(i) }()
    }
}

现象

输出:0 1 2(按逆序打印)

原因

  • 在循环体内重新定义局部变量 i,每次循环迭代都会创建一个新的局部变量 i
  • 闭包捕获的是该局部变量 i 的值(当前循环的 i),因此每个 defer 函数捕获的变量是独立的。

示例 3:通过参数传递解决陷阱

func main() {
    for i := 0; i < 3; i++ {
        defer func(i int) { println(i) }(i) // 立即传递当前 i 的值
    }
}

现象

输出:0 1 2(按逆序打印)

原因

  • defer 中定义匿名函数时,将当前 i 的值作为参数传递
  • 参数 idefer 声明时立即求值,因此每个匿名函数捕获的是循环当前迭代的 i 的值。
posted on 2025-04-23 08:00  超级无敌美少男战士  阅读(75)  评论(0)    收藏  举报