1、匿名函数(anonymous)
匿名函数是一种没有函数名的函数。
在声明匿名函数之后,在其后加上调用的参数列表,即可对匿名函数进行调用
匿名函数有两种调用执行方式:
(1)将匿名函数保存到变量,通过变量执行
(2)自执行匿名函数:在匿名函数后加调用的参数列表"()",即可对匿名函数进行立即调用
func main() {
// 将匿名函数保存到变量
add := func(x, y int) {
fmt.Println(x + y)
}
add(10, 20) // 通过变量调用匿名函数
//自执行匿名函数:匿名函数定义完加()直接执行
func(x, y int) {
fmt.Println(x + y)
}(10, 20)
}
2、闭包(Closure)
闭包=匿名函数+引用环境(外层代码定义的变量),即有状态的匿名函数,也可以说:如果匿名函数引用了外部变量,就形成了一个闭包.
在闭包的生命周期内,引用环境即变量也一直有效,会常驻于内存当中。
函数本身是不存在信息的,但是闭包中的变量使闭包本身具备了存储信息的能力。
func makeSuffixFunc(suffix string) func(string) string {
return func(name string) string {
if !strings.HasSuffix(name, suffix) {
return name + suffix
}
return name
}
}
func main() {
jpgFunc := makeSuffixFunc(".jpg")
txtFunc := makeSuffixFunc(".txt")
fmt.Println(jpgFunc("test")) //test.jpg
fmt.Println(txtFunc("test")) //test.txt
}
闭包像go协程一样在for循环时存在延迟绑定的问题。
实践:
func main() {
arr := []float64{1, 9, 16}
visit(arr, func(v float64) {
v = math.Sqrt(v)
fmt.Println("平方根", v)
})
visit(arr, func(v float64) {
v = math.Pow(v, 2)
fmt.Println("平方", v)
})
f2 := makeSuffix(".log")
fmt.Println(f2("access"))
fmt.Println(f2("access.log"))
}
// 函数做参数,可以抽象出部分公共逻辑,抽出了循环操作
func visit(lst []float64, f func(float64)) {
for _, value := range lst {
f(value)
}
}
// 函数做返回值,根据不同情形做一件相似的事,检测是否有后缀
func makeSuffix(suffix string) func(string) string {
return func(name string) string {
if !strings.HasSuffix(name, suffix) {
return name + suffix
}
return name
}
}