美文网首页
第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

相关文章

  • 29. Defer

    29. Defer 什么是 defer? defer 语句的用途是:含有 defer 语句的函数,会在该函数将要返...

  • go语言的defer语句

    go语言defer语句的用法 defer的语法 defer后面必须是函数调用语句,不能是其他语句,否则编译器会出错...

  • golang defer语句简单解析

    defer 下面举例说明了defer语句的作用: 输出结果: 很明显 defer语句的执行顺序是反的。这种语法给我...

  • defer

    defer 后面只能跟函数调用语句 defer 后面的调用语句在函数退出时调用 多个defer调用的时候,调用顺序...

  • go 的 defer 实现原理

    defer 需要注意的2点 defer 函数的参数在defer 语句出现时就已经确定func foo() { ...

  • Golang(十五)defer语句

    defer` 1.1 延迟是什么? 即延迟(defer)语句,延迟语句被用于执行一个函数调用,在这个函数之前,延迟...

  • Swift 中 defer 的介绍与使用场景

    Swift 中 defer 的介绍与使用场景 用defer语句在即将离开当前代码块时执行一系列语句。该语句让你能执...

  • 第15章-defer语句

    defer 1.1 延迟是什么? 即延迟(defer)语句,延迟语句被用于执行一个函数调用,在这个函数之前,延迟语...

  • 11 Go defer语句 && init()函数

    1、defer语句 结果 2、init()函数

  • Golang中defer用法

    Go语言中的defer语句会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时,将延迟处理的语句按d...

网友评论

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

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