第一个例子:
package main
import "fmt"
func main () {
fv := Add()
fmt.Println("fv =",fv(1)) //1
fmt.Println("fv =",fv(20)) //21
fmt.Println("fv =",fv(30)) //51
}
func Add() func(int) int {
var x int
return func(n int) int {
x += n
return x
}
}
第一个例子中,变量 fv
接收 Add()
后,实际上接收了函数 Add 返回的匿名函数,此时, fv 就成为了这个匿名函数,可以看到打印三次的结果都进行了累加。这里产生了”变量逃逸”,指的是 Add 函数体中原本的变量 x,在外部函数销毁后逃离了他原本的作用域:在将 Add 赋值给变量 fv 时, Add 就已经被销毁了。局部变量 x 也和匿名函数绑定在一起了。
闭包函数保存并积累其中的变量的值,不管外部函数退出与否,它都能够继续操作外部函数中的局部变量。
一个返回值为另一个函数的函数可以被称之为工厂函数
第二个例子 ,动态添加后辍,跟着动手做做上面的例子,再做做下面的例子,会深有体会
package main
import (
"fmt"
"strings"
)
func MakeAddSuffix(suffix string) func (string) string {
return func (name string) string {
if !strings.HasSuffix(name,suffix){
return name + suffix
}else {
return name
}
}
}
func main() {
bmps := MakeAddSuffix(".jpg")
bmps("test") //test.jpg
}
第二个例子中,外部函数 MakeAddsuffix
赋值给变量 bmps
的同时,传入了一个字符串参数 .jpg,此时函数内部会产生一个变量逃逸,参数 suffix 与匿名函数绑定。当赋值后,函数 MakeAddsuffix
的生命周期结束,返回的匿名函数与 bmps 成为了一体。
再次调用 bmps 时,传入了字符串 “test” ,首先会进行一个取反判断,传入参数 “test” 是否 “.jpg” 为后辍结束。条件成立,回返回name + suffix
这就是Go的闭包调用基本用法。还有更高阶的用法。当然这点需要你长时间的撸码习惯来积累