zoukankan      html  css  js  c++  java
  • go-defer语句

    Go语言中的defer语句也非常独特。
    defer语句仅能被放置在函数或方法中。
    它由关键字defer和一个调用表达式组成。
    调用表达式所表示的既不能是对Go语言内建函数的调用
    也不能是对Go语言标准库代码包unsafe中的那些函数的调用。
    实际上,满足上述条件的调用表达式被称为表达式语句。
    func readFile(path string) ([]byte, error) {
        file, err := os.Open(path)
        if err != nil {
            return nil, err
        }
        defer file.Close()
        return ioutil.ReadAll(file)
    }
    打开指定文件且未发现有错误发生之后,紧跟了一条defer语句。 其中携带的表达式语句表示的是对被打开文件的关闭操作。 注意,当这条defer语句被执行的时候,其中的这条表达式语句并不会被立即执行。 它的确切的执行时机是在其所属的函数(这里是readFile)的执行即将结束的那个时刻。 在readFile函数真正结束执行的前一刻,file.Close()才会被执行。 这也是defer语句被如此命名的原因。
    语句defer file.Close()的含义是在打开文件并读取其内容后及时地关闭它。
    该语句可以保证在readFile函数将结果返回给调用方之前,那个文件或目录一定会被关闭。
    这实际上是一种非常便捷和有效的保险措施。
    当一个函数中存在多个defer语句时,它们携带的表达式语句的执行顺序一定是它们的出现顺序的倒序。
    下面的示例可以很好的证明这一点:
    func deferIt() {
        defer func() {
            fmt.Print(1)
        }()
        defer func() {
            fmt.Print(2)
        }()
        defer func() {
            fmt.Print(3)
        }()
        fmt.Print(4)
    }
    deferIt函数的执行会使标准输出上打印出4321
    defer携带的表达式语句代表的是对某个函数或方法的调用。这个调用可能会有参数传入。
    如果代表传入参数的是一个表达式,那么在defer语句被执行的时候该表达式就会被求值了。
    func deferIt3() {
        f := func(i int) int {
            fmt.Printf("%d ",i)
            return i * 10
        }
        for i := 1; i < 5; i++ {
            defer fmt.Printf("%d ", f(i))
        }
    }
    它在被执行之后,标准输出上打印出1 2 3 4 40 30 20 10
    defer携带的表达式语句代表的是对匿名函数的调用,那么我们就一定要非常警惕。请看下面的示例:
    func deferIt4() {
        for i := 1; i < 5; i++ {
            defer func() {
                fmt.Print(i)
            }()
        }
    }     
    deferIt4函数在被执行之后标出输出上会出现5555,而不是4321
    原因是defer语句携带的表达式语句中的那个匿名函数包含了对外部(确切地说,是该defer语句之外)的变量的使用。
    注意,等到这个匿名函数要被执行(且会被执行4次)的时候,包含该defer语句的那条for语句已经执行完毕了。
    此时的变量i的值已经变为了5。因此该匿名函数中的打印函数只会打印出5。
    正确的用法是:把要使用的外部变量作为参数传入到匿名函数中。
    修正后如下:
    func deferIt4() {
        for i := 1; i < 5; i++ {
            defer func(n int) {
                fmt.Print(n)
            }(i)
        }
    }
  • 相关阅读:
    poj 3666 Making the Grade
    poj 3186 Treats for the Cows (区间dp)
    hdu 1074 Doing Homework(状压)
    CodeForces 489C Given Length and Sum of Digits...
    CodeForces 163A Substring and Subsequence
    CodeForces 366C Dima and Salad
    CodeForces 180C Letter
    CodeForces
    hdu 2859 Phalanx
    socket接收大数据流
  • 原文地址:https://www.cnblogs.com/osbreak/p/10402091.html
Copyright © 2011-2022 走看看