zoukankan      html  css  js  c++  java
  • Go ---- defer 和 return 执行的先后顺序

    Go 中 defer 和 return 执行的先后顺序

    1. 多个defer的执行顺序为“后进先出”;

    2. defer、return、返回值三者的执行逻辑应该是:return最先执行,return负责将结果写入返回值中;接着defer开始执行一些收尾工作;最后函数携带当前返回值退出。

    如果函数的返回值是无名的(不带命名返回值),则go语言会在执行return的时候会执行一个类似创建一个临时变量作为保存return值的动作,而有名返回值的函数,由于返回值在函数定义的时候已经将该变量进行定义,在执行return的时候会先执行返回值保存操作,而后续的defer函数会改变这个返回值(虽然defer是在return之后执行的,但是由于使用的函数定义的变量,所以执行defer操作后对该变量的修改会影响到return的值

    eg1:不带命名返回值的函数

    package main
    
    import "fmt"
    
    func main() {
    	fmt.Println("return:", test())// defer 和 return之间的顺序是先返回值, i=0,后defer
    }
    
    func test() int {//这里返回值没有命名
    	var i int
    	defer func() {
    		i++
    		fmt.Println("defer1", i) //作为闭包引用的话,则会在defer函数执行时根据整个上下文确定当前的值。i=2
    	}()
    	defer func() {
    		i++
    		fmt.Println("defer2", i) //作为闭包引用的话,则会在defer函数执行时根据整个上下文确定当前的值。i=1
    	}()
    	return i
    } 

    test() 先返回 i=0

    defer2先于defer1执行

    输出结果为:

    defer2 1

    defer1 2

    return: 0

    eg2:带命名返回值的函数:

    package main
    
    import "fmt"
    
    func main() {
    	fmt.Println("return:", test())
    }
    
    func test() (i int) { //返回值命名i 
    	defer func() {
    		i++
    		fmt.Println("defer1", i)
    	}()
    	defer func() {
    		i++
    		fmt.Println("defer2", i)
    	}()
    	return i
    }
    
    对外部变量的引用作为函数参数(i),则在defer申明时就把值传递给defer,

     

     输出结果为:

    defer2 1

    defer1 2

    return: 2

    理解return 返回值的运行机制:

    为了弄清上述两种情况的区别,我们首先要理解return 返回值的运行机制:
    return 并非原子操作,分为赋值,和返回值两步操作
    eg1 : 实际上return 执行了两步操作,因为返回值没有命名,所以
    return 默认指定了一个返回值(假设为s),首先将i赋值给s,后续
    的操作因为是针对i,进行的,所以不会影响s, 此后因为s不会更新,所以
    return s 不会改变
    相当于:
    var i int
    s := i
    return s
    eg2 : 同上,s 就相当于 命名的变量i, 因为所有的操作都是基于
    命名变量i(s),返回值也是i, 所以每一次defer操作,都会更新
    返回值i

     

  • 相关阅读:
    linux时间设置相关
    tcp/ip协议和http协议
    redis和memcache的比较
    How to Display Image In Picturebox in VC++ from Iplimage and Mat
    关于技术与业务的理解
    怎样写出好代码——设计原则
    怎么写出好代码——坏味道
    linux 用户管理
    浅谈ajax
    浅析闭包和内存泄露的问题
  • 原文地址:https://www.cnblogs.com/saryli/p/11371912.html
Copyright © 2011-2022 走看看