Golang 闭包的理解

Go里有函数类型的变量,这样,虽然不能在一个函数里直接声明另一个函数,但是可以在一个函数中声明一个匿名函数类型的变量,此时的匿名函数称为闭包(closure)。

先看一个demo:

func f(i int) func() int {
     return func() int {
         i++
         return i
     }
}

函数f返回了一个函数,返回的这个函数就是一个闭包。这个函数中本身是没有定义变量i的,而是引用了它所在的环境(函数f)中的变量i。

我们再看一下效果:

c1 := f(0)
c2 := f(0)
c1() // 打印 1
c2() // 打印 1

c1 跟 c2 引用的是不同的环境,在调用 i++ 时修改的不是同一个 i,因此两次的输出都是 1。函数 f 每进入一次,就形成了一个新的环境,对应的闭包中,函数都是同一个函数,环境却是引用不同的环境。

再看几个例子

package main

import "fmt"

func ExFunc(n int) func() {
    sum := n
    a := func() { // 把匿名函数作为值赋给变量a (Go 不允许函数嵌套, 然而你可以利用匿名函数实现函数嵌套)
        fmt.Println(sum + 1) // 调用本函数外的变量
    } // 这里没有()匿名函数不会马上执行
    return a
    //  或者直接 return 匿名函数
    //  return func() { //直接在返回处的匿名函数
    //    fmt.Println(sum + 1)
    //  }
}

func main() {
    myFunc := ExFunc(10)
    myFunc() // 这里输出11

    myAnotherFunc := ExFunc(20)
    myAnotherFunc() // 这里输出21

    myFunc()  // 这里输出11
    myAnotherFunc()  // 这里输出21
}

另一个例子:

package main

import "fmt"

func ExFunc(n int) func() {
    return func() {
        n++ // 这里对外部变量加 1
        fmt.Println(n)
    }
}

func main() {
    myFunc := ExFunc(10)
    myFunc() // 这里输出 11

    myAnotherFunc := ExFunc(20)
    myAnotherFunc() // 这里输出 21

    myFunc() // 这里输出 12
    myAnotherFunc() // 这里输出 22
}

由此得出以下两点
1.内函数对外函数 的变量的修改,是对变量的引用
2.变量被引用后,它所在的函数结束,这变量也不会马上被烧毁

闭包函数出现的条件:
1.被嵌套的函数引用到非本函数的外部变量,而且这外部变量不是“全局变量”;
2.嵌套的函数被独立了出来(被父函数返回或赋值 变成了独立的个体),而被引用的变量所在的父函数已结束.

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页