温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

golang中的defer函数

发布时间:2020-06-21 21:07:04 来源:亿速云 阅读:175 作者:鸽子 栏目:编程语言

Go语言的defer算是一个语言的新特性,至少对比当今主流编程语言如此。

defer语句调用一个函数,这个函数执行会推迟,直到外围的函数返回,或者外围函数运行到最后,或者相应的goroutine panic

每当defer执行的时候,它后面的函数值(在go中函数是一个引用类型,是一等公民,可以赋值给变量)和函数参数会被求值,但是函数不会立即调用,直到(↑)上述三种情况发生。 这就是defer的全部内容,没了,剩下就是defer的best practice

函数不会立即调用

先从最简单的开始:

func readFile(fileName string){
    f,err := os.Open(fileName)
    if err!=nil {
        return
    }
    defer f.Close()
    var content [1024]byte
    f.Read(content[:])
    fmt.Printf("%s",content)
}
func main() {
    readFile("test.data")
}

程序输出test.data前1024字节的内容。值得一提的是,类似这种open/close配对操作是defer的惯用法。 这个例子诠释了上面那句话的后半段

"但是函数不会被调用"

因为如果defer后面的f.Close()没有延迟执行,那么文件描述符都关闭了,就不会读取到任何内容。

函数值和函数参数被求值,但函数不会立即调用

下面这个例子即将诠释上半段,它来自<>,稍作修改:

func trace(funcName string) func(){
    start := time.Now()
    fmt.Printf("function %s enter\n",funcName)
    return func(){
        log.Printf("function %s exit (elapsed %s)",funcName,time.Since(start))
    }
}
 
func foo(){
    defer trace("foo()")()
    time.Sleep(5*time.Second)
}
func main(){
    foo()
    foo()
}
/*
OUTPUT:
function foo() enter
function foo() exit (elapsed 5.0095471s)
function foo() enter
function foo() exit (elapsed 5.0005382s)
*/

为什么foo会输出enter然后等待五秒左右再输出exit? 因为正如我们说的,

defer后面的函数值和参数会被求值但是实际函数调用却要等到最后

这里函数值就是trace()返回的匿名函数,函数参数当然就是字符串字面值"foo()", 对trace("foo()")的求值会输出function foo() enter, 实际函数调用trace("foo()")()即输出function foo() exit(elapsed x.x)会推迟到return执行(如果return会更新返回值变量,则会在更新后才执行defer的函数)。

杂项

多说一点,如果存在多个defer语句,最后的defer的函数的执行顺序与defer出现的顺序相反,如:

func main() {
    func1 := func(){
        fmt.Println("func1() execution deferred")
    }
    func2 := func(){
        fmt.Println("func2() execution deferred")
    }
    defer func1()
    defer func2()
    fmt.Println("strat\nworking...")
}
/*
OUTPUT:
strat
working...
func2() execution deferred
func1() execution deferred
*/

以上就是go defer(go延迟函数)介绍的详细内容,更多请关注亿速云其它相关文章!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI