Go语言中的闭包

介绍

在很多语言中都有闭包的概念,比如js,python,lua以及java中的lambda表达式,go语言中也是有的

闭包其实就是一个函数引用了它所需要的一些变量组成的

在go语言中匿名函数就是一个闭包,下面使用一下匿名函数

Go 中的匿名函数

package main

import "fmt"

func main() {
	a := 0
	// 定义一个匿名函数
	anonymousFunc := func() {
		a++
		fmt.Printf("匿名函数 %d\n", a)
	}
	// 匿名函数引用了 a 变量,每次执行方法,操作的变量应该总是同一个
	anonymousFunc()
	anonymousFunc()
	anonymousFunc()
}

执行结果

匿名函数 1
匿名函数 2
匿名函数 3

Process finished with the exit code 0

根据执行结果验证了,一个匿名函数总是持有着函数外部变量的引用。这样也有一个坏处,导致变量得不到释放,如果运用的不好,会导致内存泄漏。

使用场景

举个例子,某平台给每个用户一些初始积分,用户每发布一片文章获得相应积分,并且不影响他人积分,代码如下

package main

import "fmt"

func main() {
	// 创建账号
	juanArticle, wendellArticle := accountRegister("juan"), accountRegister("wendell")

	// 发布文章获得积分
	juanArticle()
	juanArticle()
	wendellArticle()
	wendellArticle()
	wendellArticle()
}

// 注册某平台账号
func accountRegister(name string) func() {
	integral := 10
	// 返回发布文章执行函数
	return func() {
		integral += 10
		fmt.Printf("用户%s 目前积分 %d\n", name, integral)
	}
}

执行结果

用户juan 目前积分 20
用户juan 目前积分 30
用户wendell 目前积分 20
用户wendell 目前积分 30
用户wendell 目前积分 40

Process finished with the exit code 0

注意点

Go 使用闭包也有一些坑。比如下面一段代码,希望打印 4 3 2 1 0

package main

import "fmt"

func main() {
	for i := 0; i < 5; i++ {
		defer func() {
			fmt.Println(i)
		}()
	}
}

执行结果

5
5
5
5
5

Process finished with the exit code 0

根据结果发现,打印的是 5 5 5 5 5,这是因为,每个匿名函数都引用了同一个变量,最终获取的都是一样的值。

解决匿名函数引用同一变量问题

方式一 每次都定义一个新的变量就行了

package main

import "fmt"

func main() {
	for i := 0; i < 5; i++ {
		i := i
		defer func() {
			fmt.Println(i)
		}()
	}
}

执行结果

4
3
2
1
0

Process finished with the exit code 0

方式二 将变量传入匿名函数作为行参,自然每次就引用的不是同一个变量了

package main

import "fmt"

func main() {
	for i := 0; i < 5; i++ {
		defer func(i int) {
			fmt.Println(i)
		}(i)
	}
}

执行结果

4
3
2
1
0

Process finished with the exit code 0

以上就是对闭包的简单使用啦。大家使用的时候要避免出现变量受外界干扰的情况。

欢迎关注,学习不迷路!

你可能感兴趣的:(golang,golang,开发语言,后端)