• Go语言之GO 语言变量的生命周期


    GO 语言变量的生命周期

    生命周期是指程序执行过程中变量存在的时间段。

    包变量(全局变量)和局部变量两种变量的生命周期。

    ① 包变量一直常驻在内存到程序的结束,然后被系统垃圾回收器回收。也就是说包变量的生命周期是整个程序的执行时间。
      ② 局部变量,例如一个函数中定义的变量。它有一个动态的生命周期:每次执行生命语句时创建一个新的实体,变量一直生存到它变得不可访问(例如没有外部指针指向它,函数退出我们没有路径能访问到这个变量),这时它占用的存储空间就会被回收。

    var p *int    //全局指针变量
    func f(){
        var i int
        i = 1
        p = &x    //全局指针变量指向局部变量i
    }
    
    func f(){
        p := new(int) //局部指针变量,使用new申请的空间
        *p = 1
    }
    
    i是通过var申请的局部变量,但是由于有外部指针指向访问,我们有路径可找到这个空间(变量能够逃逸出函数),所以局部变量i是申请在堆空间上。而第二个程序中p指针变量虽然是使用new申请的空间,但是由于退出函数就没有路径可寻找到它(变量无法逃出函数),所以局部变量p是申请在栈空间上的。 
    

    f函数里的x变量必须在堆上分配,因为它在函数退出后依然可以通过包一级的global变量找到,虽然它是在函数内部定义的;用Go语言的术语说,这个x局部变量从函数f中逃逸了。相反,当g函数返回时,变量*y将是不可达的,也就是说可以马上被回收的。因此,*y并没有从函数g中逃逸,编译器可以选择在栈上分配*y的存储空间(译注:也可以选择在堆上分配,然后由Go语言的GC回收这个变量的内存空间),虽然这里用的是new方式。其实在任何时候,你并不需为了编写正确的代码而要考虑变量的逃逸行为,要记住的是,逃逸的变量需要额外分配内存,同时对性能的优化可能会产生细微的影响。

    分析闭包:

    由于在定义Test( )函数时指定了返回的类型是一个匿名函数,并且该匿名函数返回的类型是整型。所以在Test( )函数中定义了一个匿名函数,并且将整个匿名函数返回,匿名函数返回的是整型。在main( )函数中定义了一个变量f,该变量的类型是匿名函数,f( )表示调用执行匿名函数。最终执行完成后发现,实现了数字的累加。虽然Test()已经返回了,但是返回的值:func()还在全局变量中使用,三次调用 f(),因此返回值会保存在堆上,即使栈释放了内存资源,但func()保存在堆中,数据不会释放。

    因为匿名函数(闭包),有一个很重要的特点:

    它不关心这些捕获了的变量和常量是否已经超出了作用域,所以只有闭包还在使用它,这些变量就还会存在。

  • 相关阅读:
    Vue学习笔记(4)-带参数路由,嵌套路由,编程式导航
    JS数组&&数组对象去重
    Vue学习笔记(3)-品牌管理系统
    Vue学习笔记(2)-组件生命周期
    负margin
    CSS布局奇淫巧计之-强大的负边距
    由浅入深漫谈margin属性
    双飞翼布局和圣杯布局的对比
    圣杯布局的实现过程
    CSS实现垂直居中的5种方法
  • 原文地址:https://www.cnblogs.com/heych/p/12577492.html
Copyright © 2020-2023  润新知