Go关键字defer的特性

栏目: IT技术 · 发布时间: 5年前

内容简介:Go里面,流程控制语句中有一个下面用代码说话。

Go里面,流程控制语句中有一个 defer 的关键字,翻译过来就是延迟的意思。

下面用代码说话。

func deferFunc() {
    defer fmt.Println("后打印")
    fmt.Println("先打印")
}

defer 在函数执行完毕之后,才会执行,所以,我们经常在释放资源或异常处理等需要收尾的场景下会用到 defer

不过 defer 也有一些“坑”,大家需要注意一下。

func printNumbers() {
    for i := 0; i < 5; i++ {
        defer func() {
            fmt.Print(i) // 输出55555
        }()
    }
}

上面例子中, defer 是在 for 循环全部执行完毕之后才会执行,所以 i 已经变成了 5 ,正确做法是下面这样

func printNumbers() {
    for i := 0; i < 5; i++ {
        defer func(j int) {
            fmt.Print(j) // 输出43210
        }(i)
    }
}

上面打印的是倒序,这是因为 defer 的执行顺序和栈的特性一样,都是 先进后出

defer 还有一个特性,当函数有参数传入时,那些参数的值会在声明时求出

func printNumbers() {
    for i := 0; i < 5; i++ {
        defer func(j int) {
            fmt.Print(j) // 输出86420
        }(i * 2)
    }
}

上面的例子大家可能看的不是很清楚,下面给过一个例子

func main() {
    i := 2
    defer fmt.Println(i) // 输出2,原因就是上面说的

    i = 8
    fmt.Println(i)
}

上面这个例子就很明显了,后面 i 如何变都不会影响 defer 输出的内容

defer 还有一个经常在面试中提到的问题,就是和 return 的执行顺序,下面是我整理的3个例子

func main() {
    fmt.Println("a return: ", a())
    fmt.Println("b return: ", b())
    fmt.Println("c return: ", *c())
}

func a() int {
    var i int

    defer func() {
        i = 1
        fmt.Println("a defer i: ", i)
    }()

    return i
}

func b() (i int) {
    defer func() {
        i = 2
        fmt.Println("b defer i: ", i)
    }()

    return i
}

func c() *int {
    var i int
    defer func() {
        i = 3
        fmt.Println("c defer i: ", i)
    }()

    return &i
}
// 输出
a defer i:  1
a return:  0
b defer i:  2
b return:  2
c defer i:  3
c return:  3

原因网上有很多优秀的解释,我就再说一下我的理解

  • a 函数之所以返回 0 ,是因为返回值是无名的, returni 的值写入返回值后, defer 再修改 i 的值,但是已经影响不到返回值了
  • b 函数之所以返回 1 ,是因为返回值已经声明成 i 了, return 之后, deferi 修改自然就影响了return的返回值了
  • c 函数结果和 a 函数不一样,是因为返回值是指针类型,一样的道理,返回值改不了,但是返回值指向的值已经更改,所以就有上面的结果

正常工作里面,虽然不可能写这种代码,但是面试的时候这些基础问题出现的频率还是挺高的,所以大家也是需要掌握一下。融汇贯通,自己多操作多试试,加深印象。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Ajax实战

Ajax实战

Dave Crane Eric Pascarello / 李锟(网名dlee) / 人民邮电出版社 / 2006年4月 / 69

本书是目前 Ajax 领域最为全面深入的一本著作,其中不仅有对于基础知识的介绍,还有对于 Ajax 开发中重大的体系架构问题的深入探讨,总结了大量 Ajax 开发中的设计模式,并讨论了框架、安全性与性能等等。书中提供了几个典型的例子,兼顾各种开发平台,这些例子的代码稍作修改就可以直接应用于项目开发之中,代码源文件可以从图灵网站下载。本书内容广泛且深入,同时适用于各个层次的 Web 应用开发人员。一起来看看 《Ajax实战》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具