Golang | 匿名函数和闭包
匿名函数
匿名函数就是一个没有名字的函数,当我们在一个函数内部重复调用一段代码, 并且这段代码不想被别的函数使用,我们就可以定义一个匿名函数,或者在一段代码需要并发的时候使用匿名函数。
例如:
func main() {
f := func() {
fmt.Println("hello,world!")
}
// 第一次调用
f()
// 第二次调用
f()
// 第三次调用
f()
// 加锁
wg := sync.WaitGroup{}
wg.Add(100)
// 并发打印一句话,100次
for i := 0; i < 100; i++ {
go func(i int) {
fmt.Printf("循环第%d次\n",i)
// 标记每一个协程的结束
wg.Done()
}(i+1)
}
// 等待所有协程都执行完毕才会结束程序
wg.Wait()
}
上面就是匿名函数的两个应用场景
闭包
闭包就是也是匿名函数的一种,它们允许调用定义在其它环境下的变量,闭包可以使当前函数捕捉到一个外部状态,一个闭包继承了函数所声明时的作用域,因此,作用域内的所有变量都被共享到了当前函数内,我们可以直接操作这个变量。闭包返回的时候,并不是单纯的返回一个函数,返回的是一个结构体,其中记录了函数返回地址和引用的环境中的变量地址。
一个简单的例子:
func AddInt() func(i int) int{
var num int
return func(i int) int {
num += i
return num
}
}
func main() {
fn := AddInt()
fmt.Println(fn(1)) // 1
fmt.Println(fn(1)) // 2
fmt.Println(fn(1)) // 3
fmt.Println(fn(1)) // 4
}
以上的小例子中,我们每一次调用fn 函数,每一次只在 addInt 中做加法,按照我们的理解应该l输出的全都是 1 ,但是现在输出的却是几次调用的和,这就说明了,在调用闭包函数的时候,当前函数可以闭包中的变量,也可以说明,闭包函数返回的 fn中,包含着函数的地址和当前环境中使用的变量地址。
看一下其它的闭包应用:
// 斐波那契数列:
func fibonacci() func() int {
a, b := 0, 1
return func() int {
a , b = b , a + b
return a
}
}
func main() {
f := fibonacci()
for i := 0; i < 10; i++ {
fmt.Println(f())
}
// 输出:
// 1
// 1
// 2
// 3
// 5
// 8
// 13
// 21
// 34
// 55
}
// 装饰器 & 中间函数
func wrapping(f func() string) {
fmt.Println("do my work...")
fmt.Println("wrapping function: ", f())
fmt.Println("my work finished !")
}
func sayHello() string {
return "Hello !"
}
func sayByeBye() string {
return "Bye Bye !"
}
func main() {
wrapping(sayHello)
wrapping(sayByeBye)
}
/*
输出:
do my work...
wrapping function: Hello !
my work finished !
do my work...
wrapping function: Bye Bye !
my work finished !
*/
关注公众号,随时获取最新资讯
细节决定成败!
个人愚见,如有不对,恳请斧正!