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 /n", 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 /n", err) 
                        //终止进程 
                        os.Exit(1) 
                }    
        }    
} 

  

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/12538.html

(0)
上一篇 2021年7月19日 14:43
下一篇 2021年7月19日 14:43

相关推荐

发表回复

登录后才能评论