• golang中的defer函数和return语句两者的执行顺序


    首先要明白,return是非原子性的,需要两步,首先要将返回值放到一个临时变量中(为返回值赋值),然后将返回值返回到被调用处。而defer函数恰在return的两个操作之间执行。

    真正的执行顺序是:

    先为返回值赋值,即将返回值放到一个临时变量中,然后执行defer,然后return到函数被调用处。

    如果所在函数为有名返回值函数,return第一步先把返回值放到有名返回值变量中,如果恰好defer函数中修改了该返回值,那么最终返回值是更新后的。但是如果所在函数为无名返回值函数,那么return第一步先把返回值放到一个临时变量中,defer函数无法获取到这个临时变量地址,所以无论defer函数做任何操作,都不会对最终返回值造成任何变动。

    看下面这个例子可以很好的理解:

    测试用例1:无名返回值(即函数返回值为没有命名的返回值)

    package main
     
    import (
            "fmt"
    )
     
    func main() {
            fmt.Println("return:", Demo()) // 打印结果为 return: 0
    }
     
    func Demo() int {
            var i int
            defer func() {
                    i++
                    fmt.Println("defer2:", i) // 打印结果为 defer: 2
            }()
            defer func() {
                    i++
                    fmt.Println("defer1:", i) // 打印结果为 defer: 1
            }()
            return i
    }

    执行结果:

    defer1: 1
    defer2: 2
    return: 0

    测试用例2:有名返回值(函数返回值为已经命名的返回值)

    package main
     
    import (
            "fmt"
    )
     
    func main() {
            fmt.Println("return:", Demo2()) // 打印结果为 return: 2
    }
     
    func Demo2() (i int) {
            defer func() {
                    i++
                    fmt.Println("defer2:", i) // 打印结果为 defer: 2
            }()
            defer func() {
                    i++
                    fmt.Println("defer1:", i) // 打印结果为 defer: 1
            }()
            return i // 或者直接 return 效果相同
    }

    执行结果:

    defer1: 1
    defer2: 2
    return: 2

    参考:Go语言中defer和return执行顺序解析

  • 相关阅读:
    【Forza Horizon 5】频繁断网解决办法
    【Java】java.util.ConcurrentModificationException
    【MySQL】下发功能SQL
    【MybatisPlus】 Field '主键' doesn't have a default value
    【SpringBoot】数据源加密处理
    【VMware】将NAT虚拟机开放访问
    TreeView绑定数据库收藏
    存储过程概述
    asp.net页面直接输出纯xml
    如何保证远程登录服务器安全
  • 原文地址:https://www.cnblogs.com/hi3254014978/p/15170593.html
Copyright © 2020-2023  润新知