目录
1.为什么会有匿名函数?
在定义函数时,不能在函数内部再定义一个函数,如果我们想要在一个函数内部再封装一个方法,就需要使用到匿名函数。
匿名函数即没有名字的函数,一个函数内部的匿名函数可以访问到这个外部函数中的变量。
下面使用一个例子来说明匿名函数的使用:
package main
import "fmt"
func main() {
var num int
num = 9
//无参匿名函数
f := func() {
num++
fmt.Println(num)
}
//f()
//将函数当做变量进行传递和调用
type FuncType func()
var f1 FuncType
f1 = f
f1()
//有参匿名函数
f2 := func(a, b int) {
var sum int
sum = a + b
fmt.Println(sum)
}
//f2(1, 2)
//此时对应的func也需要改变
type FuncType2 func(a, b int)
var f3 FuncType2
f3 = f2
f3(1, 2)
//有返回值的匿名函数,直接接受的是函数返回值
x, y := func(i, j int) (max, min int) {
max = i
min = j
return
}(100, 200)
fmt.Println(x, y)
//匿名函数主要实现的功能是闭包,闭包就是在一个函数中去访问另一个函数作用域中的变量
}
在这个例子中我们在外部函数中定义了一个变量num,然后定义了一个匿名函数,对num变量加+1。
我们使用匿名函数时若匿名函数没有返回值(对应例子中的第一个匿名函数),我们需要使用一个变量f接受这个匿名函数,f此时的类型即为这个匿名函数。于是我们通过type关键字重命名这个匿名函数func()为FuncType,并初始化一个FuncType类型的变量,这个变量可以接受f,然后通过f1()调用这个匿名函数。结果为10,说明匿名函数成功访问到变量num。
对于有参匿名函数使用方式与无参匿名函数相同 ,如例子中的第二个匿名函数
//有参匿名函数
f2 := func(a, b int) {
var sum int
sum = a + b
fmt.Println(sum)
}
//f2(1, 2)
//此时对应的func也需要改变
type FuncType2 func(a, b int)
var f3 FuncType2
f3 = f2
f3(1, 2)
对于有返回值的匿名函数,我们直接接受函数返回值即可,不需要重新调用。如:
//有返回值的匿名函数,直接接受的是函数返回值
x, y := func(i, j int) (max, min int) {
max = i
min = j
return
}(100, 200)
fmt.Println(x, y)
2.闭包
匿名函数主要实现的功能是闭包,闭包就是在一个函数中去访问另一个函数作用域中的变量。这里匿名函数和其对应的外部函数就是这个闭包关系。
我们在一个函数中返回一个匿名函数即可实现闭包。例如:
func test1() func() int {
var x int
return func() int {
x++
return x
}
}
在这个例子中,test1的返回值类型为func() int,其内部的匿名函数类型为func() int,接受的参数为test1中的变量x,通过这种方式将test1的返回值用一个变量接受后,多次调用这个变量(返回的匿名函数)不会导致x重新初始化。
func main() {
f := test1()
fmt.Println(f())
fmt.Println(f())
fmt.Println(f())
}
打印结果为1,2,3,说明多次调用函数f共用了同一个变量x。
作为对比,这里在创建一个没有闭包而定函数test:
func test() int {
var x int
x++
return x
}
func main() {
//这种情况没有使用闭包,每次调用test()都会重新初始化x,导致x始终为1
fmt.Println(test())
fmt.Println(test())
fmt.Println(test())
}
打印结果为1,1,1,说明每次调用test函数都会重新初始化函数内部的变量。