首页 > 编程笔记

什么是闭包,Go语言闭包的用法

在 Go 语言里,匿名函数就可以被称为闭包。简单来说,闭包允许调用定义在其他环境下的变量,可使得某个函数捕捉到一些外部状态,如函数被创建时的状态。

用专业的语言表述,一个闭包继承了函数声明时的作用域,作用域内的变量会共享到闭包的环境中,因此,这些变量可以在闭包中被操作,直到被销毁。

闭包经常被用作包装函数,预先定义好一个或多个参数以用于包装,另一种常见的应用就是使用包来完成更加简洁的错误检查。

什么是闭包

闭包是由函数及其相关引用环境组合而成的实体,一般通过在匿名函数中引用外部函数的局部变量或包全局变量构成。
闭包=函数+引用环境
闭包对闭包外的环境引入是直接引用,编译器检测到闭包,会将闭包引用的外部变量分配到堆上。

如果函数返回的闭包引用了该函数的局部变量(参数或函数内部变量):
闭包最初的目的是减少全局变量,在函数调用的过程中隐式地传递共享变量,有其有用的一面;但是这种隐秘的共享变量的方式带来的坏处是不够直接,不够清晰,除非是非常有价值的地方,否则一般不建议使用闭包。

对象是附有行为的数据,而闭包是附有数据的行为,类在定义时已经显式地集中定义了行为,但是闭包中的数据没有显式地集中声明的地方,这种数据和行为耦合的模型不是一种推荐的编程模型,闭包仅仅是锦上添花的东西,不是不可缺少的。

在闭包内部修改引用的变量

闭包对它作用域上部的变量可以进行修改,修改引用的变量会对变量进行实际修改,例如:
package main
import (
    "fmt"
)
func main() {
    //准备一个字符串
    str := "Apple"
    //创建一个匿名函数
    foo := func() {
        //匿名函数中访问str
        str = "Orange"
    }
    //调用匿名函数
    foo()
    fmt.Println(str)
}
在以上代码中:
运行结果如下:

Orange

如果一个函数调用返回的闭包引用修改了全局变量,则每次调用都会影响全局变量。

如果函数返回的闭包引用的是全局变量,则多次调用该函数返回的多个闭包引用的都是同一个全局变量。同理,调用一个闭包多次引用的也是同一个全局变量。此时如果闭包中修改了全局变量值的逻辑,则每次闭包调用都会影响全局变量的值。使用闭包是为了减少全局变量,所以,闭包引用全局变量不是好的编程方式。

推荐阅读