5.4 Go 闭包
闭包(closure):是由一个函数和其相关的引用环境组合的一个整体。(闭包=函数+引用环境)
package main import ( "fmt" ) //是由一个函数和其相关的引用环境组合的一个整体。(闭包=函数+引用环境) //函数addUpper返回值是个函数 //返回值是匿名函数 func(int)int func test() func(int) int { //定义一个局部变量 n := 10 //返回一个匿名函数 return func(x int) int { n += x return n } } /* addUpper函数返回了一个匿名函数,这个匿名函数又引用了函数外的变量n,因此匿名函数+n组成了一个整体,形成闭包 当调用f函数时,n仅仅被初始化一次,因此每次调用形成累计 */ func main() { //调用addUpper函数,获取返回值 f := test() //此时f是匿名函数,对其传参调用 fmt.Println(f(50)) //10+50=60 fmt.Println(f(20)) //60+20=80 fmt.Println(f(20)) //80+20=100 同一个f对象,保留了n的值 f1 := test() fmt.Println(f1(10)) }
闭包代码修改
package main import ( "fmt" ) //是由一个函数和其相关的引用环境组合的一个整体。(闭包=函数+引用环境) //函数addUpper返回值是个函数 //返回值是匿名函数 func(int)int func test() func(int) int { //定义一个局部变量 n := 10 var str = "oldboy" //返回一个匿名函数 return func(x int) int { n += x str += string(36) //36对应的 fmt.Println("此时str值:", str) return n } } /* addUpper函数返回了一个匿名函数,这个匿名函数又引用了函数外的变量n,因此匿名函数+n组成了一个整体,形成闭包 当调用f函数时,n仅仅被初始化一次,因此每次调用形成累计 */ func main() { //调用addUpper函数,获取返回值 f := test() //此时f是匿名函数,对其传参调用 fmt.Println(f(50)) //10+50=60 fmt.Println(f(20)) //60+20=80 fmt.Println(f(20)) //80+20=100 同一个f对象,保留了n的值 //新的初始化 f1 := test() fmt.Println(f1(10)) }
2. 闭包实战
package main import ( "fmt" "strings" ) /* 1.makeSuffixFunc函数接收一个文件名后缀,如.png,且返回闭包 2.调用闭包,传入文件名前缀,如果没有后缀就添加后缀,返回 文件名.png 3.strings.HasSuffix可以判断指定字符串后缀 */ func makeSuffixFunc(suffix string) func(string) string { //返回值闭包函数 return func(filename string) string { //如果没有xx后缀,执行代码 if !strings.HasSuffix(filename, suffix) { //则字符串拼接 return filename + suffix } //否则有后缀名,则直接返回新文件名 return filename } } func main() { //f1返回的是闭包函数,对此闭包函数进行功能性使用 f1 := makeSuffixFunc(".png") fmt.Println(f1("苍老师")) //没有后缀 fmt.Println("小泽老师.png") //有后缀 }
总结:
1.makeSuffixFunc函数中的变量suffix和返回值匿名函数,组合成了一个闭包 2.由于闭包函数保留了上次引用的值suffix,只需要传入一次,即可反复使用
2.1. 函数式编程
支持将函数作为另一个函数的参数,叫回调函数。
支持将函数作为另一个函数的返回值。
package main import "fmt" //闭包函数 //函数体内有局部变量 func adder() func(int) int { sum := 0 //return 的是一个闭包 return func(v int) int { //引用自由变量,sum sum += v return sum } } //递归定义 type iAdder func(int) (int, iAdder) //函数式编程写法,函数+常量 func adder2(base int) iAdder { return func(v int) (int, iAdder) { return base + v, adder2(base + v) } } func main() { // a := adder() is trivial and also works. a := adder2(0) for i := 0; i < 10; i++ { var s int s, a = a(i) fmt.Printf("0 + 1 + ... + %d = %d ", i, s) } }
go闭包-斐波那契数列
package main import "fmt" // 1,1,2,3,5,8,13,21,34,55... // func fibonacci() func() int { a, b := 0, 1 return func() int { a, b = b, a+b return a } } func main() { f := fibonacci() //斐波那契数列 fmt.Println(f()) fmt.Println(f()) fmt.Println(f()) fmt.Println(f()) fmt.Println(f()) fmt.Println(f()) fmt.Println(f()) fmt.Println(f()) fmt.Println(f()) fmt.Println(f()) }
2.2. python中闭包
def adder(): sum = 0 def f(value): nonlocal sum sum +=value return sum return f