美文网首页
defer延迟调用的详细用法

defer延迟调用的详细用法

作者: Mr丶易客 | 来源:发表于2018-12-10 20:46 被阅读74次
          ***喜欢走一波***
defer是什么?

关键字 defer ⽤于注册延迟调⽤。这些调⽤直到 return前才被执⾏,通常⽤于释放资源或错误处理。

一、在没有错误的情况下,defer的执行顺序,与调用函数参数问题

先举个例子

package main

import (
    "fmt"
)

//defer 压栈
func largest(num []int) {
    defer fmt.Println("finished1")
    defer fmt.Println("finished2")
    item := num[0]
    for _, v := range num {
        if item < v {
            item = v
        }
    }
    println("最大值:", item)
}
func myInt(m int) {
    fmt.Println(m)
}
func main() {
    defer fmt.Println("main1")
    m := 90
    defer myInt(m)   //defer 调用的函数参数值在压栈时已确定 
    m = 100
    num := []int{1, 2, 3, 4, 5, 6}
    largest(num)  //多个defer的调用顺序
    defer fmt.Println("main2")
}

执行结果

最大值: 6
finished2
finished1
main2
90               //这里输出是90
main1

根据上面的例子可以看出defer相当于一个栈,先进后出,并且defer调用的函数参数值在压栈时便已确定

二、关于defer与错误处理共同存在问题(简单一说)

panic 抛出错误, recover 捕获错误。

package main

import (
    "fmt"
)

func myRecover() {

    if r := recover(); r != nil {   //捕获错误recover()  为捕获到为 nil
        fmt.Println("MyRecovered", r)  
        // debug.PrintStack()   //打印错误
    }
    fmt.Println("myRecover执行")
}
func a() {
    defer myRecover()
    arr := []int{1, 2, 3}
    fmt.Println(arr[3])   //这是个错误  不存在arr[3],然后去执行defer
    fmt.Println("Mya")   //不执行
}
func main() {
    defer myRecover()   //此处defer 因为错误已经处理  所以捕获不到
    a()
    fmt.Println("MyMain")
}

执行结果

MyRecovered runtime error: index out of range
myRecover执行
MyMain
myRecover执行

对于panic的作用 和上面的arr[3]一样 都是用来抛出异常

package main

import (
    "fmt"
)
//
//错误panic 的使用
func recoverName() { //recover
    if r := recover(); r != nil {
        fmt.Println("recovered from", r)
    }

}
func fullName(firstName *string, lastName *string) {
    // defer fmt.Println("defer fullName函数") //限制性defer在执行panic
    defer recoverName() //捕获解决问题

    if firstName == nil {
        panic("First Name can't be null")
    }
    if lastName == nil {
        panic("Last Name can't be null")
    }
    fmt.Printf("%s,%s\n", *firstName, *lastName)
    fmt.Println("returned normallu from fullName")
}
func test() {
    // defer recoverName()
    // defer fmt.Println("defer test函数")
    first := "Hello"
    fullName(&first, nil)
}
func main() {
    defer fmt.Println("defer main函数")
    test()
    fmt.Println("main overed")
}

输出结果

recovered from Last Name can't be null
main overed
defer main函数

总结:简而言之就是下面两句话

  • 当发生panic之后,如果当前函数使用了recover,则捕获了这个 错误,权限交给上一层调用者,正常执行剩下的代码。
  • 如果当前函数没有使用recover,上一层调用者函数使用了recover,则属于调用者捕获了错误,将权限交给上一层调用者的调用者 然后正常执行剩下代码

关于异常抛出与处理的更详细内容参考:
https://www.jianshu.com/p/18dfd4772cdb

相关文章

  • defer延迟调用的详细用法

    defer是什么? 关键字 defer ⽤于注册延迟调⽤。这些调⽤直到 return前才被执⾏,通常⽤于释放资源或...

  • Go函数-延迟调用(三)

    在go语言里,defer可是实现延迟函数调用。语句defer向当前函数注册稍后执行的函数调用。这些调用被称做延迟调...

  • Go 延迟调用 defer 用法详解

    引子 概述 defer (延迟调用)是 Go语言中的一个关键字,一般用于释放资源和连接、关闭文件、释放锁等。和de...

  • Golang(十五)defer语句

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

  • 第15章-defer语句

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

  • defer延迟调用

  • 深入理解 Go-Defer的机制

    defer 的作用和执行时机 go 的 defer 语句是用来延迟执行函数的,而且延迟发生在调用函数 return...

  • Golang learning 函数 function

    函数 匿名函数未使用为报错 延迟调用 defer

  • 15. defer语句延迟函数的执行

    当函数中有defer语句,会延迟此语句的执行,直到函数返回后才执行。 defer后面的是参数延迟调用的参数是立刻生...

  • Go语言之defer

    定义 defer语句被用于预定对一个函数的调用。我们把这类被defer语句调用的函数称为延迟函数。 注意,defe...

网友评论

      本文标题:defer延迟调用的详细用法

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