基本介绍

闭包就是 一个函数 和其相关的 引用环境 组合的一个整体
好处: 保存引用的变量,下次继续使用,不会销毁

代码

  1. package main
  2. import "fmt"
  3. // 累加器
  4. // 闭包 - 函数柯里化
  5. // 返回值类型: func(int) int
  6. func AddUpper() func(int) int {
  7. var n int = 100
  8. return func(i int) int {
  9. n = n + i
  10. return n
  11. }
  12. }
  13. func main() {
  14. f := AddUpper()
  15. fmt.Println(f(1)) // 101
  16. fmt.Println(f(2)) // 103
  17. fmt.Println(f(3)) // 106
  18. }

说明

  1. AddUpper是一个函数,返回的数据类型 func(int) int
  2. 闭包的说明

image.png
返回的是一个匿名函数,但是这个匿名函数引用到了函数外的变量 n ,因此这个匿名函数就和 n 形成一个整体,构成闭包

  1. 当反复调用 f 函数时,因为 n 只初始化一次,保存了变量的值,因此每调用一次就相当于进行了累加。
  2. 我们要搞清楚闭包,关键就是要分析返回的函数使用到哪些变量

    代码分析

    ```go package main

import ( “fmt” )

// 累加器 // 闭包 - 函数柯里化 // 返回值类型: func(int) int func AddUpper() func(int) int { var n int = 100 var str = “hello” return func(i int) int { n = n + i fmt.Println(“i=”, i) str += string(36) // ascii 36 = ‘$’ fmt.Printf(“str==%s\n”, str) return n } }

func main() { f := AddUpper() // fmt.Println(AddUpper()(1)) // 101 fmt.Println(“f(1)=”, f(1)) // 101 fmt.Println(“f(2)=”, f(2)) // 103 fmt.Println(“f(3)=”, f(3)) // 106 }

i= 1 str==hello$ f(1)= 101 i= 2 str==hello$$ f(2)= 103 i= 3 str==hello$$$ f(3)= 106

  1. <a name="lzEYc"></a>
  2. # 闭包案例
  3. 需求:
  4. 1. 编写一个函数 makeSuffix(suffix string) ,可以接收一个文件后缀名,并返回一个闭包
  5. 2. 调用闭包,可以传入一个文件名,如果该文件名没有指定后缀,则返回 文件名.jpg ,如果已经有.jpg,则返回原文件名。
  6. strings.HasSuffix,该函数可以判断某个字符串是否有指定的后缀。
  7. <a name="Nzfgc"></a>
  8. ## 上代码
  9. ```go
  10. package main
  11. import (
  12. "fmt"
  13. "strings"
  14. )
  15. /*
  16. 需求:
  17. 1. 编写一个函数 makeSuffix(suffix string) ,可以接收一个文件后缀名,并返回一个闭包
  18. 2. 调用闭包,可以传入一个文件名,如果该文件名没有指定后缀,则返回 文件名.jpg ,
  19. 如果已经有.jpg,则返回原文件名。
  20. strings.HasSuffix ,该函数可以判断某个字符串是否有指定的后缀。
  21. */
  22. func makeSuffix(suffix string) func(string) string {
  23. return func(name string) string {
  24. if !strings.HasSuffix(name, suffix) {
  25. return name + suffix
  26. }
  27. return name
  28. }
  29. }
  30. // 传统写法
  31. func makeSuffixV2(suffix string, name string) string {
  32. if !strings.HasSuffix(name, suffix) {
  33. return name + suffix
  34. }
  35. return name
  36. }
  37. func main() {
  38. // 闭包调用
  39. f := makeSuffix(".jpg")
  40. fmt.Println(f("xiao")) // xiao.jpg
  41. fmt.Println(f("xiaoxiao.jpg")) // xiaoxiao.jpg
  42. fmt.Println(f("xiaoxiao.666")) // xiaoxiao.666.jpg
  43. // 传统写法调用
  44. fmt.Println("makeSuffixV2=", makeSuffixV2(".jpg", "allblue")) // makeSuffixV2= allblue.jpg
  45. fmt.Println("makeSuffixV2=", makeSuffixV2(".jpg", "all.blue")) // makeSuffixV2= all.blue.jpg
  46. }

说明

返回的匿名函数和 makeSuffix(suffix string) 的 suffix 变量组合成一个闭包

传统写法和闭包写法实现效果一样,但是,传统写法需要重复写变量, 比如上面的
makeSuffixV2(“.jpg”, “all.blue”))
闭包则解决了这个问题,是代码看起来更加的简洁

闭包的好处之一: 参数复用

好处: 保存引用的变量,下次继续使用,不会销毁

函数柯里化(闭包)

参考我的另一篇文章: https://www.yuque.com/xiaojt/izub4k/ps5oet