78捕鱼游戏手机下载 当前位置:首页>78捕鱼游戏手机下载>正文

78捕鱼游戏手机下载

发布时间:2018-11-14

原标题:学习一门新语言需要了解的基础-15 闭包

学习一门新语言需要了解的基础-15 闭包


本节内容

  • 何为闭包
  • 闭包通过指针引用环境变量
  • 闭包导致环境变量生命周期延长和堆分配
  • 闭包怎么调用的[付费阅读]
  • 闭包与数据竞争

何为闭包

$ cat test.go
package main

func test(x int) func() {
    println("test.x :", &x)
    
    return func() {
        println("closure.x :", &x, x)
    }
}

func main() {
    f := test(100)
    f()
}

闭包最常用的例子是,一个匿名函数引用了它的上下文对象x,那么我们把这种状态称之为闭包。

闭包通过指针引用环境变量

闭包严格意义上来说,由两个东西组成的,函数加上环境变量,这两个东西合起来称之为闭包。闭包我们都知道有这样一个问题,比如说有一个函数,函数内部有个环境变量x,当它返回一个匿名函数的时候,这个函数是通过指针访问环境变量x的,并不是把环境变量x复制过去,用指针引用环境变x量实际上会造成这个局部变量x在堆上分配,生命周期延长。以代码为例,test函数访问之后test代码就结束了,结束了以后它的栈帧就失效了,这样再去引用变量x的时候肯定会有问题,我们知道你不能引用地址空间已经无效的内容,所以会造成这个x从栈上逃逸到堆上。

闭包导致环境变量生命周期延长和堆分配

我们看下是否逃逸到堆上了:

$ go build -gcflags "-N -l -m" -o test test.go
./test.go:6:12: func literal escapes to heap
./test.go:6:12: func literal escapes to heap
./test.go:7:33: &x escapes to heap
./test.go:3:22: moved to heap: x #我们可以看到moved to heap:x
./test.go:4:25: test &x does not escape
./test.go:7:32: test.func1 &x does not escape

因为只有把x放到堆上时候,当我们去执行f()时候,对象才能在堆上找到,不用担心它在栈上会被覆盖掉。所以这就会造成一个问题闭包会导致它所引用的环境变量生命周期延长,原来test()函数执行结束以后x的值就失效了,现在呢?test()函数虽然执行结束了,但是x值依然存在,为什么要存在?因为当我们执行f()调用代码时候x不存在就出错了,所以x的生命周期必然延长,延长就必须从当前栈帧上逃逸到堆上,才有可能在调用时候依然有效的。

闭包怎么调用的[付费阅读]

闭包与数据竞争

闭包可能引起数据竞争,刚刚我们知道闭包是通过指针引用环境变量,比如说一个函数有个x,同时返回两个匿名函数,这两个匿名函数都引用x的情况下,他们都持有x的指针,当两个匿名函数都对x并发操作时,就会形成数据竞争效应,因为两个匿名函数都用不同线程执行时,他们同时去访问x就会引起数据竞争,理论上我们需要对它加锁处理。

$ cat race.go
package main

import "time"

func test(x int) (func(), func()) {

    // 尽管 x 不是指针,但闭包内部通过指针引用,所以
    // 也会导致数据竞争(data race)发生。

    w := func() {
            for {
                x++
            }
        }

    r := func() {
           for {
               _ = x
            }
        }

    return w, r
}

func main() {
    w, r := test(100)
    
    go w()
    go r()

    time.Sleep(time.Second * 10)
}
$ go run -race race.go #-race参数用于数据竞争检查

闭包实际上是由两个东西组成的,第一个匿名函数,第二个环境变量,合起来才叫闭包。不同的语言对闭包的处理不太一样。

当前文章:http://neomi.cn/liushisi/7151.html

发布时间:2018-11-14 00:26:11

德扑圈发牌原理 豪利棋牌下载地址 棋牌游戏大全排行榜 手机棋牌代理怎么做 天天电玩城充值官网 天天电玩城官网下载 天天乐棋牌卡五星 万豪娱乐网址 网络棋牌游戏网站 网上打棋牌网站输钱

27440 56148 68976 98679 27020 6840285660 23958 23541

责任编辑:乙邓扁

随机推荐