一、概念
1、闭包在各种各样计算机语言上都能寻找适用的地区,造成也较为早。闭包(Closure)是词法闭包的通称,就如人们念书情况下学过的结合总闭包的定义一样。对闭包的界定有很多种多样叫法,大致能够 分成下列两大类:
- 一种说法认为闭包是符合一定条件的函数,比如这样定义:闭包是在其词法上下文中引用了自由变量的函数。
- 另一种说法认为闭包是有函数和其相关的引用环境组合而成的实体。比如这样定义:在实现深约束时,需要创建一个能显示表示引用环境的东西,并将它与相关的子程序捆绑在一起,这样捆绑起来的整体被称为闭包。即:函数+引用环境=闭包。
2、上面的定义,一个认为闭包是函数,一个认为闭包是函数和环境引用组成的整体。显然第二种说法更确切,闭包只是表现像函数,但实际上不是函数。
- 函数是一些可执行的代码,这些代码在函数被定义后就确定了,不会再执行时发生变化,所以一个函数只有一个实例。
- 闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。
3、闭包在某些编程语言中被称为“Lambda表达式”。
4、函数本身不存储任何信息,只有与引用环境结合后形成的闭包才具有记忆性,函数是编译器静态的概念,而闭包是运行期动态的概念。
5、对象是附有行为的数据,而闭包是附有数据的行为。
二、闭包的价值
1、加强模块化
- 闭包有助于模块化编程,它能以简单的方式开发较小的模块,从而提高开发速度和程序的可复用性。可以将模块划分的更小。
2、抽象
- 闭包是数据和行为的组合,这使得闭包具有较好的抽象能力,
3、简化代码
三、一个编程语言需要哪些特性来支持闭包
1、函数是一阶值,即函数可以作为另一个函数的返回值或者参数,还可以作为一个变量的值;
2、函数可以嵌套定义,即在一个函数内部可以定义另一个函数。
3、允许定义匿名函数。
4、可以捕获引用环境,并把环境和函数代码组成一个可调用的实体。
四、案例1:不使用闭包进行计数
package main import "fmt" func main() { for i:=0;i<10;i++{ fmt.Printf("i=%d t",i) fmt.Println(add(i)) }} func add(num int) int { sum := 0 sum += num return sum}
输出结果:
i=0 0i=1 1i=2 2i=3 3i=4 4i=5 5i=6 6i=7 7i=8 8i=9 9
可以看出来,sum每次都归零,无法完成我们的计数功能。
2、使用闭包完成计数功能
package mainimport "fmt"func main() { res := adder() fmt.Printf("%T n",res) for i:=0;i<5;i++{ fmt.Printf("i=%d t",i) fmt.Println(res(i)) }}// using closure// return a functionfunc adder() func(int) int{ sum := 0 res := func(num int) int{ sum += num return sum } return res}
输出结果如下:
func(int) int i=0 0i=1 1i=2 3i=3 6i=4 10
可以看出,res的类型是一个返回值为int的函数,输出的结果,每次都在上一个结果的基础上累加进行计数。
总结:
正常情况下,GC会对我们不用的变量进行清除,保证程序的运行效率。但是,如何识别一个变量是“垃圾”呢,即 没有任何引用指向它,简单的说就是没有任何程序用到它。而现在的 sum虽然是函数内的局部变量,但是adder函数一直被赋值给res变量,导致adder中的sum变量一直被使用,所以sum会一直存在并被进行累加。
本文来源于:Go语言函数与指针(三)---闭包-变化吧门户
特别声明:以上文章内容仅代表作者本人观点,不代表变化吧门户观点或立场。如有关于作品内容、版权或其它问题请于作品发表后的30日内与变化吧联系。
- 赞助本站
- 微信扫一扫
-
- 加入Q群
- QQ扫一扫
-
评论