闭包
2024-05-19 00:56
阅读 269
在编程中,闭包是一种特殊的函数,它由一个函数和这个函数所在的环境组合而成。
这个定义或许有些抽象,让我们用一个自然界的例子来说明一下。当你在山林间漫步时,你看到了一只蜜蜂在花朵间飞舞,而这只蜜蜂身上的花粉不知不觉地黏在了你的衣服上。闭包就像这只蜜蜂,是一个带有环境的函数,也像这只蜜蜂携带花粉一样携带着某些变量。
闭包中的函数可以访问其创建时所在的上下文中的变量,即使在离开那个作用域之后也可以。通俗点讲,闭包就是在另外一个函数中创建的函数,并且可以访问该函数的变量。可以认为闭包是另外一个函数的“子函数”。
举个简单的例子,有这样一个函数:
▼go复制代码func A() func() int { i := 0 b := func() int { i++ return i } return b }
函数 A 返回一个函数,这个函数会返回一个变量 i,并且每次返回的 i 值为前一次的值加 1。
接下来通过一段代码来说明一下:
▼go复制代码a := A() // a 类型是 func() int,此时 i 的值为 0。 fmt.Println(a()) // 输出 1,i 的值为 1。 fmt.Println(a()) // 输出 2,i 的值为 2。 fmt.Println(a()) // 输出 3,i 的值为 3。 b := A() // b 类型是 func() int,新创建一个函数,此时 i 的值为 0。 fmt.Println(b()) // 输出 1,i 的值为 1。 fmt.Println(b()) // 输出 2,i 的值为 2。 fmt.Println(a()) // 输出 4,i 的值为 4。
上面这段代码中,通过函数 A 返回的函数 b 重复调用,每次调用 i 的值都会自增 1。另外,当我们用函数 A 再次创建一个新的函数 b 时,i 的值会重新被初始化为 0。
这里有一个需要注意的地方,闭包能够访问到外部变量,是因为它的生命周期一直持续到它不再被使用。所以上面的代码中,函数 A 返回的函数 b 能够一直访问变量 i 是因为被调用的函数一直存在于内存中,而非立即被垃圾回收掉了。
闭包的应用场景可以是任何需要获得函数内部变量值的场景,比如迭代器模式、延迟(defer)执行等。了解闭包的概念及其应用,可以让你写出更加灵活、高效的 Go 代码。
标签:
