美文网首页
第15章-defer语句

第15章-defer语句

作者: Venture_Mark | 来源:发表于2018-10-15 18:13 被阅读0次

    defer

    1.1 延迟是什么?

    即延迟(defer)语句,延迟语句被用于执行一个函数调用,在这个函数之前,延迟语句返回。

    1.2 延迟函数

    你可以在函数中添加多个defer语句。当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回。特别是当你在进行一些打开资源的操作时,遇到错误需要提前返回,在返回前你需要关闭相应的资源,不然很容易造成资源泄露等问题

    • 如果有很多调用defer,那么defer是采用后进先出模式
    • 在离开所在的方法时,执行(报错的时候也会执行)
    func ReadWrite() bool {
        file.Open("file")
        defer file.Close()
        if failureX {
              return false
        } i
        f failureY {
              return false
        }
        return true
    }
    
    

    最后才执行file.Close()

    示例代码:

    package main
    
    import "fmt"
    
    func main() {
        a := 1
        b := 2
        defer fmt.Println(b)
        fmt.Println(a)
    }
    
    

    运行结果:

    1
    2
    
    

    示例代码:

    package main
    
    import (
        "fmt"
    )
    
    func finished() {
        fmt.Println("Finished finding largest")
    }
    
    func largest(nums []int) {
        defer finished()
        fmt.Println("Started finding largest")
        max := nums[0]
        for _, v := range nums {
            if v > max {
                max = v
            }
        }
        fmt.Println("Largest number in", nums, "is", max)
    }
    
    func main() {
        nums := []int{78, 109, 2, 563, 300}
        largest(nums)
    }
    
    

    运行结果:

    Started finding largest
    Largest number in [78 109 2 563 300] is 563
    Finished finding largest
    
    

    1.3 延迟方法

    延迟并不仅仅局限于函数。延迟一个方法调用也是完全合法的。让我们编写一个小程序来测试这个。

    示例代码:

    package main
    
    import (
        "fmt"
    )
    
    type person struct {
        firstName string
        lastName string
    }
    
    func (p person) fullName() {
        fmt.Printf("%s %s",p.firstName,p.lastName)
    }
    
    func main() {
        p := person {
            firstName: "John",
            lastName: "Smith",
        }
        defer p.fullName()
        fmt.Printf("Welcome ")
    }
    
    

    运行结果:

    Welcome John Smith
    
    

    1.4 延迟参数

    延迟函数的参数在执行延迟语句时被执行,而不是在执行实际的函数调用时执行。

    让我们通过一个例子来理解这个问题。

    示例代码:

    package main
    
    import (
        "fmt"
    )
    
    func printA(a int) {
        fmt.Println("value of a in deferred function", a)
    }
    func main() {
        a := 5
        defer printA(a)
        a = 10
        fmt.Println("value of a before deferred function call", a)
    
    }
    
    

    运行结果:

    value of a before deferred function call 10
    value of a in deferred function 5
    
    

    1.5 堆栈的推迟

    当一个函数有多个延迟调用时,它们被添加到一个堆栈中,并在Last In First Out(LIFO)后进先出的顺序中执行。

    我们将编写一个小程序,它使用一堆defers打印一个字符串。示例代码:

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        name := "Naveen"
        fmt.Printf("Orignal String: %s\n", string(name))
        fmt.Printf("Reversed String: ")
        for _, v := range []rune(name) {
            defer fmt.Printf("%c", v)
        }
    }
    
    

    运行结果:

    Orignal String: Naveen
    Reversed String: neevaN
    
    

    1.6 延迟的应用

    到目前为止,我们所写的示例代码,并没有实际的应用。现在我们看一下关于延迟的应用。在不考虑代码流的情况下,延迟被执行。让我们以一个使用WaitGroup的程序示例来理解这个问题。我们将首先编写程序而不使用延迟,然后我们将修改它以使用延迟,并理解延迟是多么有用。

    示例代码:

    package main
    
    import (
        "fmt"
        "sync"
    )
    
    type rect struct {
        length int
        width  int
    }
    
    func (r rect) area(wg *sync.WaitGroup) {
        if r.length < 0 {
            fmt.Printf("rect %v's length should be greater than zero\n", r)
            wg.Done()
            return
        }
        if r.width < 0 {
            fmt.Printf("rect %v's width should be greater than zero\n", r)
            wg.Done()
            return
        }
        area := r.length * r.width
        fmt.Printf("rect %v's area %d\n", r, area)
        wg.Done()
    }
    func main() {
        var wg sync.WaitGroup
        r1 := rect{-67, 89}
        r2 := rect{5, -67}
        r3 := rect{8, 9}
        rects := []rect{r1, r2, r3}
        for _, v := range rects {
            wg.Add(1)
            go v.area(&wg)
        }
        wg.Wait()
        fmt.Println("All go routines finished executing")
    }
    
    

    修改以上代码:

    package main
    
    import (
        "fmt"
        "sync"
    )
    
    type rect struct {
        length int
        width  int
    }
    
    func (r rect) area(wg *sync.WaitGroup) {
        defer wg.Done()
        if r.length < 0 {
            fmt.Printf("rect %v's length should be greater than zero\n", r)
            return
        }
        if r.width < 0 {
            fmt.Printf("rect %v's width should be greater than zero\n", r)
            return
        }
        area := r.length * r.width
        fmt.Printf("rect %v's area %d\n", r, area)
    }
    func main() {
        var wg sync.WaitGroup
        r1 := rect{-67, 89}
        r2 := rect{5, -67}
        r3 := rect{8, 9}
        rects := []rect{r1, r2, r3}
        for _, v := range rects {
            wg.Add(1)
            go v.area(&wg)
        }
        wg.Wait()
        fmt.Println("All go routines finished executing")
    }
    
    

    程序运行结果:

    rect {8 9}'s area 72
    rect {-67 89}'s length should be greater than zero
    rect {5 -67}'s width should be greater than zero
    All go routines finished executing
    
    

    相关文章

      网友评论

          本文标题:第15章-defer语句

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