js闭包循环原因_go|闭包

闭包是由函数及其相关引用环境组合而成的实体,一般通过在匿名函数中引用外部函数的局部变量或包变量构成。

闭包=匿名函数+引用环境(外部函数的局部变量或者全局变量)

闭包对闭包外的环境引入是直接引用,编译器检测到闭包,会将闭包引用的外部变量分配到堆上。

闭包引用全局变量不是好的编程方式。

闭包经常被用作包装函数,预先定义好一个或多个参数用于包装,另一种常见的应用就是使用闭包来完成更加简洁的错误检查。

如果函数返回的闭包引用了该函数的局部变量(参数或函数内部变量):

1、多次调用该函数,返回的多个闭包所引用的外部变量是多个副本,原因是每次调用函数都会为局部变量分配内存。

2、用一个闭包函数多次,如果该闭包修改了其引用的外部变量,则每次调用该闭包对该外部变量都有影响,因为闭包函数共享外部应用。

package mainimport "fmt"func calc(a int) func(i int) int {// var a int =1 // 也可以在这里声明变量return func(i int) int { // 返回的是一个匿名函数,但是这个匿名函数引用到函数外的a,因此这个匿名函数和a就形成了一个整体,构成闭包。fmt.Printf("外部变量a的地址:%p,a的值为:%d,入参i的地址为:%p, 入参i的值为:%d",&a, a, &i, i)a = a + ireturn a}}func main() {f := calc(1) // 函数对象f和外部变量a是一个整体,是一个闭包g := calc(1)fmt.Println(f(1)) // 修改了变量afmt.Println(f(1))fmt.Println(f(1))fmt.Println(g(1))fmt.Println(g(1))}
d40bb6306f42491d22568be3306f827b.png

同一个函数返回的多个闭包共享该函数的局部变量

package mainimport "fmt"func calc(a int) (func(i int) int, func(i int) int) {add := func(i int) int {fmt.Printf("外部变量a的地址:%p,a的值为:%d,入参i的地址为:%p, 入参i的值为:%d",&a, a, &i, i)a = a + ireturn a}sub := func(i int) int {a = a - ireturn a}return add, sub}func main() {f, g := calc(1) // 函数对象f,g 和入参1组成闭包,是一个整体m, n := calc(1)// 初始a=1,f(1)=2,此时a=2,由于f,g,a=2是一个整体,所以,g(2)=0fmt.Println(f(1), g(2))fmt.Println(m(4), n(6))}

即,两个返回的匿名函数和外部变量a,组成一个整体,是一个闭包

1caa114b7be373e78ee488cfb0e801e9.png

Goroutine与闭包

package mainimport ("fmt""sync""time")var a = [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9}func Run() {fmt.Println("Begin", time.Now())var wg sync.WaitGroupwg.Add(len(a))for _, i := range a {go func(n int) { // 函数变量是以值的方式传递的fmt.Printf("get value: %d ", n)time.Sleep(time.Second)wg.Done()}(i)/*go func(){// 由于for循环非常快,而启动Goroutine是一个费时操作,// 所以Goroutine还没开始执行,for循环已经执行完毕,此时i=5// 由于i是所有Goroutine匿名函数的外部变量,所以所有的Goroutine只会打印5fmt.Printf("get value: %d ", i)time.Sleep(time.Second)wg.Done()}()*/}wg.Wait()fmt.Println("End", time.Now())}func main() {Run()}
d262b3bc3f169fb9bc398c8e87ccddcd.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值