zoukankan      html  css  js  c++  java
  • golang中defer的些许总结

    引言

    最近自己在学习go项目的时候,查看别人的源码经常发现defer的使用,加上自己之前对这个关键字没怎么在意,只知道差不多是用来释放内部变量的。

    查看资料可以发现,defer会在当前函数或者方法返回之前执行传入的函数,经常用于关闭文件描述符、关闭数据库连接以及解锁资源

    为了能够更形象地理解defer的行为,我就在这贴上一段关闭文件描述符的示例代码:

    func CopyFile(source, dest string) bool {
        if source == "" || dest == "" {
            log.Println("source or dest is null")
            return false
        }
        source_open, err := os.Open(source)
        if err != nil {
            log.Println(err.Error())
            return false
        }
        defer source_open.Close()
        dest_open, err := os.OpenFile(dest, os.O_CREATE|os.O_WRONLY, 644)
        if err != nil {
            log.Println(err.Error())
            return false
        }
        defer dest_open.Close()
        _, copy_err := io.Copy(dest_open, source_open)
        if copy_err != nil {
            log.Println(copy_err.Error())
            return false
        } else {
            return true
        }
    }
    

    在示例代码中,使用了defer来关闭文件流,用来避免忘记文件释放的问题。

    defer的调用时机以及多次调用defer的执行顺序

    defer传入的函数会在当前调用方法返回之前得到运行。

    为了更好地解释上面的原理,通过一个简单例子来观察就很明显了:

    func main() {
        for i := 0; i < 4; i++ {
            defer fmt.Println(i)
        }   
    }
    

    示例程序中是用来循环输出数字的,实际上的运行结果如下,可以观察得出defer的效果类似于栈的先进后出:

    3 
    2 
    1 
    0
    

    defer的预计算参数

    defer继承了Go中函数调用的特性,就是函数调用都是传值的。所以,使用defer关键字之后,会立刻对函数中引用的外部参数进行拷贝

    示例程序如下,最后包含了输出结果:

    func PrintInfo() {
        val := 0
        fmt.Println("use defer to print val-->")
        // in here, will output 0
        defer fmt.Println(val)
        val++
        // in here, will output 1
        defer fmt.Println(val)
        return
    }
    
    use defer to print val--> 
    1 
    0
    

    至于程序为什么会输出1 0 而不是 0 1 ,答案已经在上面有了解释;

    参考资料

  • 相关阅读:
    IE的F12开发人员工具不显示问题
    CENTOS 6.5 平台离线编译安装 PHP5.6.6
    PHP 5.6 编译安装选项说明
    CENTOS 6.5 平台离线编译安装 Mysql5.6.22
    CENTOS 6.5 平台离线安装 Apache2.4
    Bringing Whoops Back to Laravel 5
    在 Laravel 中使用图片处理库 Integration/Image
    让 windows 下的命令行程序 cmd.exe 用起来更顺手
    Laravel Composer and ServiceProvider
    VisualStudio2013 如何打开之前版本开发的(.vdproj )安装项目
  • 原文地址:https://www.cnblogs.com/zuixime0515/p/13289087.html
Copyright © 2011-2022 走看看