zoukankan      html  css  js  c++  java
  • [日常] Go语言*-Deferred函数

    1.只需要在调用普通函数或方法前加上关键字defer,就完成了defer所需要的语法。当defer语句被执行时,跟在defer后面的函数会被延迟执行。直到包含该defer语句的函数执行完毕时,defer后的函数才会被执行,不论包含defer语句的函数是通过return正常结束,还是由于panic导致的异常结束

    2.defer语句经常被用于处理成对的操作,如打开、关闭、连接、断开连接、加锁、释放锁。通过defer机制,不论函数逻辑多复杂,都能保证在任何执行路径下,资源被释放。释放资源的defer应该直接跟在请求资源的语句后

    3.defer语句会先调用,defer后面的函数会最后调用,两层函数,配合返回匿名函数函数值实现trace功能
    defer trace("bigSlowOperation")()

    4.http响应写入文件 n, err = io.Copy(f, resp.Body)

    练习5.18:不修改fetch的行为,重写fetch函数,要求使用defer机制关闭文件。

    package main
    
    //导入io/ioutil和net/http包
    import (
            "fmt"
            "io"
            "os"
            //"io/ioutil"
            "net/http"
            "strings"
            //"time"
            "net/url"
    )
    /*
    练习5.18:不修改fetch的行为,重写fetch函数,要求使用defer机制关闭文件。
    */
    func main() {
            //开始时间
            //start := time.Now()
            //for循环命令行参数
            for _, u := range os.Args[1:] {
                    //加入前缀
                    if !strings.HasPrefix(u, "http://") {
                            u = "http://" + u 
                    }   
                    res, err := http.Get(u)
                    //判断错误
                    if err != nil {
                            //向标准错误流打印信息
                            fmt.Fprintf(os.Stderr, "fetch:%v 
    ", err)
                            //终止进程
                            os.Exit(1)
                    }   
                    //使用defer机制
                    defer res.Body.Close()
    
                    urlObj, _ := url.Parse(u)
                    filename := urlObj.Path
                    if filename == "/" {
                            filename = "index.html"
                    }   
                    var f *os.File
                    f, err = os.Create(filename)
                    //使用defer机制
                    /*  
                    我们没有对f.close采用defer机制,因为这会产生一些微妙的错误。许多文件系统,尤其是NFS,写入文件时发生的错误会被延迟到文件关闭时反馈。如果没有检查文件关闭时的反馈信息,可能会导致数
    据丢失,而我们还误以为写入操作成功。如果io.Copy和f.close都失败了,我们倾向于将io.Copy的错误信息反馈给调用者,因为它先于f.close发生,更有可能接近问题的本质。
                    */
                    defer f.Close()
                    _, err = io.Copy(f, res.Body)
                    //判断错误
                    if err != nil {
                            //向标准错误流打印信息
                            fmt.Fprintf(os.Stderr, "fetch:%v 
    ", err)
                            //终止进程
                            os.Exit(1)
                    }   
            }   
    }
    

      

  • 相关阅读:
    HDU 4389 数位dp
    Codeforces Round #405 (rated, Div. 2, based on VK Cup 2017 Round 1)A B C 水 并查集 思路
    Codeforces Round #385 (Div. 2)A B C 模拟 水 并查集
    Codeforces Round #404 (Div. 2)A B C二分
    HDU 2586 倍增法求lca
    Codeforces Round #209 (Div. 2)A贪心 B思路 C思路+快速幂
    Codeforces Round #384 (Div. 2) A B C D dfs序+求两个不相交区间 最大权值和
    vim出现“E212: Can't open file for writing”的处理办法
    centos7 开机/etc/rc.local 不执行的问题
    CentOS 系统状况查看
  • 原文地址:https://www.cnblogs.com/taoshihan/p/8877651.html
Copyright © 2011-2022 走看看