匿名函数是一种没有函数名的函数,即定义即使用;闭包作为一种携带状态的函数,我们可以简单地将它理解为“对象”,因为它同时具备状态和行为。
匿名函数
匿名函数没有函数名,只有函数体,它只有在被调用的时候才会初始化。匿名函数一般被当作一种类型赋值给函数类型的变量,经常被用作回调函数。
Go语言的匿名函数的声明样式如下所示:
func(params)(return params) {
function body
}
匿名函数的声明与普通函数的定义基本一致,只是没有名字。我们可以在匿名函数声明之后直接调用它,如下所示:
func (name string) {
fmt.Println("My name is ", name)
}('小明')
在声明匿名函数之后,在其后加上调用的参数列表,即可对匿名函数进行调用。除此之外,我们还可以将匿名函数赋值给函数的变量,用于多次调用或者求值,如下所示:
currentTime := func() {
fmt.Println(time.Now())
}
// 调用匿名函数
currentTime()
上述例子中,通过匿名函数实现了一个简单的报时器,并赋值给 currentTime,我们每次调用
currentTime` 都能知道当前系统的最新时间。
匿名函数一个比较常用的场景是用作回调函数。
实例:使用回调函数处理字符串
它接收 string
和匿名函数的参数输入,然后使用匿名函数对 string
进行处理。
package main
import "fmt"
func proc(input string, proessor func(str string)) {
// 调用匿名函数
processor(input)
}
func main() {
proc("小明", func(str string) {
for _, v := range str {
fmt.Printf("%c
", v)
}
})
闭包
闭包是携带状态的函数,它是将函数内部和函数外部连接起来的桥梁。通过闭包,我们可以读取函数内部的变量。我们也可以使用闭包封装私有状态,让它们常驻于内存当中。
闭包能够引用其作用域上部的变量并进行修改,被捕获到闭包中的变量将随着闭包的生命周期一直存在,函数本身是不存在信息的,但是闭包中的变量使闭包本身具备了存储信息的能力。
实例:利用闭包的特效实现一个简单的计数器
package main
import "fmt"
func createCounter(initial int) func() int {
if initial < 0 {
initial = 0
}
// 引用 initial,创建一个闭包
return func() int {
initial++
// 返回当前计数
return initial;
}
}
func main() {
// 计数器 1
c1 := createCounter(1)
fmt.Println(c1()) // 2
fmt.Println(c2()) // 3
// 计数器 2
c2 := createCounter(10)
fmt.Println(c2()) // 11
fmt.Println(c1()) // 4
}
不同的闭包之间变量不会互相干扰,c1和c2两个计数器都是独立进行计数。