您的位置 首页 golang

golang2021函数与包(19)Go语言闭包实践

    Go语言闭包

    闭包并不是什么新奇的概念,它早在高级语言开始发展的年代就产生了。

    1、闭包的概念

    闭包(Closure)是词法闭包(Lexical  Closure)的简称。是由函数和与其相关的引用环境组合而成的实体。在实现深约束时,需要创建一个能显式表示引用环境的东西,并将它与相关的子程序捆绑在一起,这样捆绑起来的整体被称为闭包。函数  + 引用环境 = 闭包。

     

    闭包只是在形式和表现上像函数,但实际上不是函数。函数是一些可执行的代码,这些代码在函数被定义后就确定了,不会在执行时发生变化,所以一个函数只有一个实例。

     

    闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。闭包在某些编程语言中被称为  Lambda 表达式。

     

    函数本身不存储任何信息,只有与引用环境结合后形成的闭包才具有“记忆性”。函数是编译器静态的概念,而闭包是运行期动态的概念。

     

    对象是附有行为的数据,而闭包是附有数据的行为。

    2、闭包的优点

    1) 加强模块化

    闭包有益于模块化编程,便于以简单的方式开发较小的模块,从而提高开发速度和程序的可复用性。和没有使用闭包的程序相比,使用闭包可将模块划分得更小。

     

    比如要计算一个数组中所有数字的和,只需要循环遍历数组,把遍历到的数字加起来就行了。如果现在要计算所有元素的积,又或者要打印所有的元素呢?解决这些问题都要对数组进行遍历,如果是在不支持闭包的语言中,程序员不得不一次又一次重复地写循环语句。而这在支持闭包的语言中是不必要的。这种处理方法多少有点像回调函数,不过要比回调函数写法更简单,功能更强大。

    2) 抽象

    闭包是数据和行为的组合,这使得闭包具有较好的抽象能力。

    3) 简化代码

    一个编程语言需要以下特性来支持闭包。

    • 函数是一阶值(First-class       value,一等公民),即函数可以作为另一个函数的返回值或参数,还可以作为一个变量的值;

    • 函数可以嵌套定义,即在一个函数内部可以定义另一个函数;

    • 允许定义匿名函数;

    • 可以捕获引用环境,并把引用环境和函数代码组成一个可调用的实体。

    接下来通过三个示例的对比来更清晰地了解闭包的作用。

     

    【示例】没有使用闭包进行计数的代码。

     

    1. package       main

    2. import “fmt”

    3. func main() {

    4. for i := 0; i < 5; i++ {

    5. fmt.Printf(“i=%d       \t”, i)

    6. fmt.Println(add2(i))

    7. }

    8. }

    9. func add2(x int) int {

    10. sum := 0

    11. sum += x

    12. return sum

    13. }

    运行结果如下:

    i=0     0

    i=1     1

    i=2     2

    i=3     3

    i=4     4

    由上面的示例可以看出,for 循环每执行一次,sum 都会清零,没有实现 sum 累加计数。

     

    【示例】使用闭包函数实现计数器。

     

    1. package       main

    2. import “fmt”

    3. func main() {

    4. pos := adder()

    5. for i := 0; i < 10; i++       {

    6. fmt.Printf(“i=%d       \t”, i)

    7. fmt.Println(pos(i))

    8. }

    9. fmt.Println(“——————–“)

    10. for i := 0; i < 10; i++       {

    11. fmt.Printf(“i=%d       \t”, i)

    12. fmt.Println(pos(i))

    13. }

    14. }

    15. func adder() func(int) int       {

    16. sum := 0

    17. return func(x int) int {

    18. fmt.Printf(“sum1=%d       \t”, sum)

    19. sum += x

    20. fmt.Printf(“sum2=%d       \t”, sum)

    21. return sum

    22. }

    23. }

    运行结果如下:

    i=0     sum1=0   sum2=0  0

    i=1     sum1=0   sum2=1  1

    i=2     sum1=1   sum2=3  3

    i=3     sum1=3   sum2=6  6

    i=4     sum1=6   sum2=10     10

    i=5     sum1=10     sum2=15     15

    i=6     sum1=15     sum2=21     21

    i=7     sum1=21     sum2=28     28

    i=8     sum1=28     sum2=36     36

    i=9     sum1=36     sum2=45     45

    ——————–

    i=0     sum1=45     sum2=45     45

    i=1     sum1=45     sum2=46     46

    i=2     sum1=46     sum2=48     48

    i=3     sum1=48     sum2=51     51

    i=4     sum1=51     sum2=55     55

    i=5     sum1=55     sum2=60     60

    i=6     sum1=60     sum2=66     66

    i=7     sum1=66     sum2=73     73

    i=8     sum1=73     sum2=81     81

    i=9     sum1=81     sum2=90     90

    【示例】闭包使用案例。

     

    1. package       main

    2. import “fmt”

    3. func main() {

    4. myfunc := Counter()

    5. //       fmt.Printf(“%T\n”, myfunc)

    6. fmt.Println(“myfunc”,       myfunc)

    7. // 调用 myfunc 函数,i变量自增 1 并返回

    8. fmt.Println(myfunc())

    9. fmt.Println(myfunc())

    10. fmt.Println(myfunc())

    11. // 创建新的函数 nextNumber1,并查看结果

    12. myfunc1 := Counter()

    13. fmt.Println(“myfunc1”,       myfunc1)

    14. fmt.Println(myfunc1())

    15. fmt.Println(myfunc1())

    16. }

    17. //计数器,闭包函数

    18. func Counter() func() int {

    19. i := 0

    20. res := func() int {

    21. i += 1

    22. return i

    23. }

    24. // fmt.Printf(“%T, %v       \n”, res, res)

    25. fmt.Println(“Counter       中的内部函数:”, res)

    26. return res

    27. }

    运行结果如下:

    Counter 中的内部函数:  0x49ac50

    myfunc 0x49ac50

    1

    2

    3

    Counter 中的内部函数:  0x49ac50

    myfunc1 0x49ac50

    1

    2

    由于闭包函数“捕获”了和它在同一作用域的其他常量和变量,所以当闭包在任何地方被调用,闭包都可以使用这些常量或者变量。它不关心这些变量是否已经超出作用域,只要闭包还在使用这些变量,这些变量就依然存在。

文章来源:智云一二三科技

文章标题:golang2021函数与包(19)Go语言闭包实践

文章地址:https://www.zhihuclub.com/97070.shtml

关于作者: 智云科技

热门文章

网站地图