01 背景

最近在从0开始撸golang,刚看到闭包这这一章节,觉得不管是视频还是书中的解释都有些晦涩,刚好目前工作中会用到 Python/Golang/Groovy 三种编程语言,在此总结一下三种编程语言中闭包的特点与基本使用

关于编程中的闭包,可以参考这篇文章,我觉得叙述的很深刻:理解Python 闭包概念

02 Golang 中的闭包

函数在Golang中是“一等公民”,闭包更是函数的高级用法,那什么是闭包呢,我觉得可以理解为:一个外部函数 其函数体内部还定义了一个内部函数,这个内部函数引用了外部的一个自由变量,其中外部函数的返回值是内部函数的引用,那么匿名函数及其引用的环境(包括变量等)就构成了一个闭包。

我们来看一个例子

其中 Checkfile 这个函数在执行后就得到了一个闭包,而闭包又是一个特殊的函数,就可以直接拿来调用。

这里最特殊的一点就是: 返回的闭包并不是单存的一个函数,它是有状态的,这个闭包里记录了它引用的环境及变量,所以外部函数结束后引用的环境和变量并不会被释放

03 Python 中的闭包

Python 的闭包我觉得和 Golang 比较类似,也是外部函数内定义了内部函数,内部函数访问了外部函数体内的变量,外部函数返回值是内部函数的引用

看如下这个示例:

从上面这个示例,我们可以明显得出以下结论:

  • 闭包中的引用的自由变量只和具体的闭包有关联,闭包的每个实例引用的自由变量互不干扰。
  • 一个闭包实例对其自由变量的修改会被传递到下一次该闭包实例的调用。

闭包在Python 中的应用很大一部分是作为装饰器来使用,关于装饰器,待研究透彻后会另外写一篇文章记录,这里我们先看看Python 闭包中的一个隐藏的雷。

这里如果很多同学不仔细看,可能会认为输出的答案分别是

0

1

4

然实际执行会发现,返回的是

4

4

4

这里问题就来了,在第一个例子中我们总结了不同闭包实例之间的自由变量相互独立,但是在上面这个例子上看貌似自由变量i都是一样的,受到了影响?

实际上,这里有个偷换的概念

result = outer_func(),这句执行后result 并不是一个闭包,而是一个三个函数的列表,在func 这个函数真正执行前, i 这个变量已经变成了2 !!!

所以以下两点特别需要注意

  • 返回闭包中不要引用任何循环变量,或者后续会发生变化的变量,正确做法是当成参数场地给内部函数
  • 如果返回的函数中没有引用父函数中定义的local variable,那么返回的函数不是闭包函数

04 Groovy 中的闭包

到了Groovy 这,画风就有点不太一样了,groovy 中的闭包定义并不像Golang、Python中那样,而是一个由 { }包含的代码块,这个代码块可以接收参数,也可以赋值给变量...

我们来看看groovy 中各式各样的 闭包

闭包如何执行

闭包的返回值

在Groovy 中,咋一看闭包和方法也太像了,但是实际上闭包一定是有返回值的,一般返回的是最后一条语句的值或者return 后的值,如果没有则为null,但是方法是可以没有返回值的

闭包和函数的区别

1.返回值

2.同理 Python、Golang ,Groovy 中的闭包也是会记录上下文的信息的,所以如果引用了自由变量,这个自由变量的状态是会跟随闭包