美文网首页go学习go
go的defer用法范例

go的defer用法范例

作者: 咕咕鷄 | 来源:发表于2017-01-15 17:16 被阅读43次

    摘抄整理自《the way to go》

    关键字defer允许我们推迟到函数返回之前(或任意位置执行return语句之后)一刻才执行某个语句或函数(为什么要在返回之后才执行这些语句?因为return语句同样可以包含一些操作,而不是单纯地返回某个值)。

    关键字defer的用法类似于面向对象编程语言 Java 和 C# 的finally语句块,它一般用于释放某些已分配的资源。

    通常我们会将一些函数的收尾工作通过defer执行,使代码结构更清晰。

    package main
    
    import "fmt"
    
    func main() {
        doDBOperations()
    }
    
    func connectToDB() {
        fmt.Println("ok, connected to db")
    }
    
    func disconnectFromDB() {
        fmt.Println("ok, disconnected from db")
    }
    
    func doDBOperations() {
        connectToDB()
        fmt.Println("Defering the database disconnect.")
        defer disconnectFromDB() //function called here with defer
        fmt.Println("Doing some DB operations ...")
        fmt.Println("Oops! some crash or network error ...")
        fmt.Println("Returning from function here!")
        return //terminate the program
        // deferred function executed here just before actually returning, even if
        // there is a return or abnormal termination before
    }
    

    接下来看一些另类用法
    使用 defer 语句实现代码追踪

    package main
    
    import "fmt"
    
    //一个基础但十分实用的实现代码执行追踪的方案就是在进入和离开某个函数打印相关的消息,即可以提炼为下面两个函数:
    func trace(s string)   { fmt.Println("entering:", s) }
    func untrace(s string) { fmt.Println("leaving:", s) }
    
    func a() {
        trace("a")
        defer untrace("a")
        fmt.Println("in a")
    }
    
    func b() {
        trace("b")
        defer untrace("b")
        fmt.Println("in b")
        a()
    }
    
    func main() {
        b()
    }
    

    输出:

    entering: b
    in b
    entering: a
    in a
    leaving: a
    leaving: b
    

    上面的代码还可以修改为更加简便的版本

    package main
    
    import "fmt"
    
    func trace(s string) string {
        fmt.Println("entering:", s)
        return s
    }
    
    func untrace(s string) {
        fmt.Println("leaving:", s)
    }
    
    func a() {
        defer untrace(trace("a"))
        fmt.Println("in a")
    }
    
    func b() {
        defer untrace(trace("b"))
        fmt.Println("in b")
        a()
    }
    
    func main() {
        b()
    }
    

    使用 defer 语句来记录函数的参数与返回值

    下面的代码展示了另一种在调试时使用 defer 语句的手法

    package main
    
    import (
        "io"
        "log"
    )
    
    func func1(s string) (n int, err error) {
        defer func() {
            log.Printf("func1(%q) = %d, %v", s, n, err)
        }()
        return 7, io.EOF
    }
    
    func main() {
        func1("Go")
    }
    
    

    输出:

    Output: 2011/10/04 10:46:11 func1("Go") = 7, EOF
    

    我是咕咕鸡,一个还在不停学习的全栈工程师。
    热爱生活,喜欢跑步,家庭是我不断向前进步的动力。

    相关文章

      网友评论

        本文标题:go的defer用法范例

        本文链接:https://www.haomeiwen.com/subject/syzybttx.html