Golang Defer

作者: Wenchao | 来源:发表于2019-03-18 22:39 被阅读0次

Defer

Go的控制流有一些常用的机制:if, for, switch, goto. 它也拥有可以在独立的goroutine中运行代码的go语句。接下来会介绍通常比较少用到的类型:defer, panic, recover.

defer语句将函数调用压入一个列表。当包围defer的函数返回的时候,列表中缓存的调用开始执行。Defer语句是用来简化各种各样的清除操作的

例如,当需要打开两个文件,将其中一个文件的内容拷贝到另外一个文件的时候:

func CopyFile(dstName, srcName string) (written int64, err error) {
    src, err := os.Open(srcName)
    if err != nil {
        return
    }
    
    dst, err := os.Create(dstName)
    if err != nil {
        return
    }
    
    written, err = io.Copy(dst, src)
    dst.Close()
    src.Close()
    return
}

上面的代码可以工作,但是会有一个Bug。如果调用os.Create失败,这个函数就会立即返回却没有关闭源文件。当然,可以在出现error的地方加上src.Close方法,但是如果这个函数非常复杂,这个问题就会很难被注意到。当引入defer语句,这个问题就会很容易被解决:

func CopyFile(dstName, srcName string) (written int64, err error) {
    src, err := os.Open(srcName)
    if err != nil {
        return
    }
    defer src.Close()
    
    dst, err := os.Create(dstName)
    if err != nil {
        return
    }
    defer dst.Close()
    
    return io.Copy(dst, src)
}

Defer 语句可以确保我们打开文件之后会关闭这些文件,不管函数中有多少个return语句。

Defer 语句的行为非常直接,可以预测。有三个简单的规则:

  1. defer语句指定的函数中的变量是当执行到defer语句的时候就确定了的;
    在下面的例子中,表达式“i”的值当Println被defer的时候就确定了的,所以下面的输出是0,而不是1

    func a() {
        i := 0
        defer fmt.Println(i)
        i++
        return
    }
    
  2. 多个defer 语句执行的顺序是后进先出的。
    下面的函数打印“3210”

    func b() {
        for i := 0; i < 4; i++ {
            defer fmt.Print(i)
        }
    }
    
  3. 被Defer的函数可以读取并且修改外层函数的被命名的返回值
    在下面的例子中,当外层函数返回的时候,defer函数执行,并且将返回值加1,所以这个函数返回的是2.

    func c() (i int) {
        defer func() {i++} ()
        return 1
    }
    

相关文章

  • Golang之Defer

    引用 golang defer实现原理 Golang之轻松化解defer的温柔陷阱 Golang中defer、re...

  • 2017-12-04

    Golang,Panic,Defer,Recover 在golang中,recover在defer里发挥作用。 一...

  • go defer理解

    golang的defer是怎么工作的?defer在golang里是一个很基础的关键字,在函数内部使用defer声明...

  • golang中defer执行时机与常见问题

    defer是什么? defer的用途 defer的执行时机 了解defer的执行时机首先要知道golang的ret...

  • 聊聊golang的defer

    序 本文主要研究一下golang的defer defer return先赋值(对于命名返回值),然后执行defer...

  • 12 Golang defer panic recover

    defer Golang中的defer会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时,将延迟处...

  • 2017-11-23 step

    1 Golang的返回值,return,defer 多个defer的顺序是stack顺序,FILO 正确的顺序是:...

  • Golang defer

    话题起于同事在微信群里发了张图,是Go Newsletter于13日在Twitter上转的一个代码截图,问输出是啥...

  • golang defer

    The arguments to the deferred function (which include the...

  • Golang Defer

    Defer Go的控制流有一些常用的机制:if, for, switch, goto. 它也拥有可以在独立的gor...

网友评论

    本文标题:Golang Defer

    本文链接:https://www.haomeiwen.com/subject/rdbimqtx.html