zoukankan      html  css  js  c++  java
  • Go语言中defer语句使用小结

    defer是Go语言中的延迟执行语句,用来添加函数结束时执行的代码,常用于释放某些已分配的资源、关闭数据库连接、断开socket连接、解锁一个加锁的资源。Go语言机制担保一定会执行defer语句中的代码。其它语言中也有类似的机制,比如Java、C#语言里的finally语句,C++语言里的析构函数(Destructor)可以起类似的作用,C++语言机制担保在对象被销毁前一定会执行析构函数中的代码。C++中的析构函数析构的是对象,Go中的defer析构的是函数。

    一、defer语句执行时机

    defer语句在函数返回之前 或者 函数中 return语句(return语句可能调用另一个函数) 之后执行。示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    package main
     
    import (
        "fmt"
    )
     
    func main() {
        fmt.Println(deferReturn())
    }
     
    func deferReturn() (ret int) {
        defer func() {
            ret++
        }()
        return 10
    }

    上述代码打印出来的值是:11。 defer语句 匿名函数中的“ret++” 对返回值 10 加 1 变成了 11。再来看一个defer语句出现在return语句之后的代码:

    1
    2
    3
    4
    5
    6
    7
    8
    func returnDefer() (ret int) {
        return 0
        defer func() {
            ret++
            ret++
        }()
        return 1
    }

    上述returnDefer函数的返回值是:0。原因是defer语句还没有添加上代码执行到"return 0"函数就返回了,因此defer语句就没有执行。

    二、多个defer语句的执行顺序是逆序执行

    当出现多条 defer 语句时以逆序执行(类似栈,即后进先出)。示例代码:

    1
    2
    3
    4
    5
    func deferSample() {
        for i := 0; i < 5; i++ {
            defer fmt.Printf("%d ", i)
        }
    }

    上述代码将会输出:4 3 2 1 0

    三、defer与panic

    1、在panic语句后面的defer语句不被执行

    示例代码:

    1
    2
    3
    4
    func panicDefer() {
        panic("panic")
        defer fmt.Println("defer after panic")
    }

    上述代码的输出如下:

    panic: panic

    goroutine 1 [running]:
    main.panicDefer()
        E:/godemo/testdefer.go:17 +0x39
    main.main()
        E:/godemo/testdefer.go:13 +0x20

    Process finished with exit code 2

    可以看到 defer 语句没有执行。

    2、在panic语句前的defer语句会被执行

    示例代码:

    1
    2
    3
    4
    func deferPanic() {
        defer fmt.Println("defer before panic")
        panic("panic")
    }

    上述代码的输出如下:

    defer before panic
    panic: panic

    goroutine 1 [running]:
    main.deferPanic()
        E:/godemo/testdefer.go:19 +0x95
    main.main()
        E:/godemo/testdefer.go:14 +0x20

    Process finished with exit code 2

    defer 语句输出了内容。

    Go中的panic类似其它语言中的抛出异常,panic后面的代码不再执行(panic语句前面的defer语句会被执行)。

    四、return 的实现逻辑

    1、第一步给返回值赋值(若是有名返回值直接赋值,匿名返回值 则 先声明再 赋值) ;
    2、第二步调用RET返回指令并传入返回值,RET会检查是否存在defer语句,若存 在就先逆序插播 defer语句 ;
    3、最后 RET 携带返回值退出函数 。

    可以看出 , return 不是一个原子操作,函数返回值与 RET 返回值并不一定一致。

    五、defer、 return、返回值三者顺序

    defer、 return、返回值 三者的执行顺序是 : return 最先给返回值赋值;接着 defer 开始执行一些收尾工作;最后 RET 指令携带返回值退出函数。

    参考 https://www.cnblogs.com/aiandbigdata/p/10822123.html

  • 相关阅读:
    【模拟】Gym
    【二分】【半平面交】Gym
    【凸包】【三分】Gym
    【字符串哈希】【哈希表】Aizu
    【思路】Aizu
    【树状数组】Codeforces Round #423 (Div. 1, rated, based on VK Cup Finals) C. DNA Evolution
    【构造】Codeforces Round #423 (Div. 1, rated, based on VK Cup Finals) B. High Load
    【贪心】Codeforces Round #423 (Div. 1, rated, based on VK Cup Finals) A. String Reconstruction
    【模拟退火】Petrozavodsk Winter Training Camp 2017 Day 1: Jagiellonian U Contest, Monday, January 30, 2017 Problem F. Factory
    【动态规划】【二分】Petrozavodsk Winter Training Camp 2017 Day 1: Jagiellonian U Contest, Monday, January 30, 2017 Problem B. Dissertation
  • 原文地址:https://www.cnblogs.com/show58/p/12604265.html
Copyright © 2011-2022 走看看