• defer原理、性能、优化


    1、defer执行时机

    for i:=1;i<10;i++{
        defer log.Println(i)
    }
    

    上面那段简单的代码基本就可以说明多个defer时的执行顺序了

    当代码中出现defer时,会将defer要执行的函数压人栈,然后等函数执行完毕再执行defer栈中的内容

    go1.13以前用堆分配,加入到链表中,再尾递归调用,go1.13在栈上分配,如果defer过多则还是会在堆上用链表来管理

    go1.14则做了进一步优化,defer的开销基本很小了。


    2、defer的估值时刻

    defer的赋值操作并不是延迟赋值的,还是按照语句顺序赋值的

    如下:

    //defer初始化值和位置有关 推迟执行的仅仅是函数体
    func f3(j int) (i int)  {
    
    
    	defer func(a int) {
    		i += a
    		log.Println("------------",j) //退出阶段j=100 进入阶段j=10 a=10
    	}(j)
    
    	j =100   //defer初始化值和位置有关
    	return
    }
    

    如果我们如下调用

    f3(10)
    

    a的值为10,而打印的j最后会被打印100

    defer分为进入阶段退出阶段


    在看下面的例子

    func f4(j int) (i int)  {
    
    	j =100   //defer初始化值和位置有关
    	defer func(a int) {
    		i += a
    	}(j)
    
    	return
    }
    

    a=100


    3、防止defer内存泄漏

    下面这段代码会严重占用内存栈,造成短暂内存泄漏,有大量的文件句柄没有被释放

    //内存泄漏
     func writeManyFiles(files []os.File) error {
    	 for _, file := range files {
    
             defer file.Close()
    
    	 }
    	 return nil
     }
    

    用函数包裹之后每循环一个就关闭一个文件句柄

    //防止内存泄漏
     func writeManyFiles(files []os.File) error {
    	 for _, file := range files {
    
    	 	if err:= func() error {
    			f, err := os.Open(file)
    			defer f.Close()
    			if err != nil {
    				return err
    			}else {
    				return nil
    			}
    		}();err!=nil{
    			return err
    		}
    
    	 }
    	 return nil
     }
    
  • 相关阅读:
    第三周动手动脑
    判断回文串
    补码&&反码&&原码小知识
    第二周课后学习作业&&动手动脑课后作业
    Topcoder Tian Ji‘s Horse Racing
    Dining kuangbin
    网络流算法
    kuangbin Doing Homework
    kuangbin Prime Path
    ZOJ4033 CONTINUE...?
  • 原文地址:https://www.cnblogs.com/biningooginind/p/12488386.html
Copyright © 2020-2023  润新知