MST

星途 面试题库

面试题:Go语言匿名函数作用域的基础理解

请解释在Go语言中,匿名函数内部如何访问外部作用域的变量,并举一个简单的代码示例说明可能出现的作用域陷阱。
10.4万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

匿名函数访问外部作用域变量

在Go语言中,匿名函数可以直接访问外部作用域的变量,因为Go语言的匿名函数是闭包。闭包是一个函数值,它引用了其函数体之外的变量。当这个函数被调用时,被引用的变量会被保留,即使外部作用域已经结束。

代码示例及作用域陷阱

package main

import (
    "fmt"
)

func main() {
    var funcs []func()
    for i := 0; i < 3; i++ {
        funcs = append(funcs, func() {
            fmt.Println(i)
        })
    }
    for _, f := range funcs {
        f()
    }
}

在上述代码中,预期输出是 0 1 2,但实际输出是 3 3 3。这就是一个作用域陷阱。原因是在 for 循环中,i 是同一个变量,匿名函数捕获的是 i 的引用,而不是 i 的值。当 for 循环结束时,i 的值已经变为 3,所以当所有匿名函数执行时,输出的都是 3

解决这个问题的一种方法是在每次循环时创建一个新的变量来保存 i 的值:

package main

import (
    "fmt"
)

func main() {
    var funcs []func()
    for i := 0; i < 3; i++ {
        j := i
        funcs = append(funcs, func() {
            fmt.Println(j)
        })
    }
    for _, f := range funcs {
        f()
    }
}

这样修改后,每次循环都会创建一个新的 j 变量,每个匿名函数捕获的是不同的 j 值,输出就会是预期的 0 1 2