golang关键字defer/panic/recover

defer的执行顺序:多个defer出现的时候,它是一个“栈”的关系,也就是先进后出

defer与return谁先谁后:return语句先执行,defer语句后执行

package main

import "fmt"

func deferFunc() int {
    fmt.Println("defer func called")
    return 0
}

func returnFunc() int {
    fmt.Println("return func called")
    return 0
}

func returnAndDefer() int {

    defer deferFunc()

    return returnFunc()
}

func main() {
    returnAndDefer()
}

函数的返回值会先初始化成零值

package main

import "fmt"

func DeferFunc1(i int) (t int) {

	fmt.Println("DeferFunc1中的t = ", t)

	return 2
}
func DeferFunc2(i int) (t int) {

	return 2
}

func main() {
	DeferFunc1(10)
	fmt.Print("DeferFunc2中的t = ", DeferFunc2(10))
}

只要声明函数的返回值变量名称,就会在函数初始化时候为之赋值为零值,而且在函数体作用域可见

  • 对于值类型:布尔类型为 false, 数值类型为 0,字符串为 "",数组和结构体会递归初始化其元素或字段,即其初始值取决于元素或字段。
  • 对于引用类型: 均为 nil,包括指针 pointer,函数 function,接口 interface,切片 slice,管道 channel,映射 map

有名函数返回值遇见defer情况 

package main

import "fmt"

func returnButDefer() (t int) {  //1.初始化0, 并且作用域为该函数全域

    defer func() {
        t = t * 10 //3.
    }()

    return 1 //2.
}

func main() {
    fmt.Println(returnButDefer())
}

defer遇见panic

遇到panic时,执行defer。

如果没有遇到recover,执行完defer后,向stderr抛出panic信息。

遇到recover则停止panic,返回recover处继续往下执行。

A. defer遇见panic,但是并不recover(捕获异常)的情况

package main

import (
    "fmt"
)

func main() {
    defer_call()

    fmt.Println("main 正常结束")
}

func defer_call() {
    defer func() { fmt.Println("defer: panic 之前1") }()
    defer func() { fmt.Println("defer: panic 之前2") }()

    panic("异常内容")  //触发defer出栈

    defer func() { fmt.Println("defer: panic 之后,永远执行不到") }()
}

B. defer遇见panic,并recover(捕获异常)

package main

import (
	"fmt"
)

func main() {
	defer_call()

	fmt.Println("main 正常结束")
}

func defer_call() {

	defer func() {
		fmt.Println("defer: panic 之前1, 捕获异常")
		if err := recover(); err != nil {
			fmt.Println(err)
		}
	}()

	defer func() { fmt.Println("defer: panic 之前2, 不捕获") }()

	panic("异常内容") //触发defer出栈

	defer func() { fmt.Println("defer: panic 之后, 永远执行不到") }()
}

defer 最大的功能是 panic 后依然有效 所以defer可以保证你的一些资源一定会被关闭,从而避免一些异常出现的问题。要养成打开资源,下一行就是defer 关闭资源的习惯。

defer中包含panic 

revover只会捕获最新的panic

触发panic("panic")后defer顺序出栈执行,第一个被执行的defer中 会有panic("defer panic")异常语句,这个异常将会覆盖掉main中的异常panic("panic"),最后这个异常被第二个执行的defer捕获到。

package main

import (
	"fmt"
)

func main() {

	defer func() {
		if err := recover(); err != nil {
			fmt.Println(err)
		} else {
			fmt.Println("fatal")
		}
	}()

	defer func() {
		panic("defer panic")
	}()

	panic("panic")
}

defer下的函数参数包含子函数

package main

import "fmt"

func function(index int, value int) int {

    fmt.Println(index)

    return index
}

func main() {
    defer function(1, function(3, 0))
    defer function(2, function(4, 0))
}
  • defer压栈function1,压栈函数地址、形参1、形参2(调用function3) —> 打印3
  • defer压栈function2,压栈函数地址、形参1、形参2(调用function4) —> 打印4
  • defer出栈function2, 调用function2 —> 打印2
  • defer出栈function1, 调用function1—> 打印1

defer内变量的值是何时确定的? (补充1)

package main

import (
   "fmt"
)

func function(value int) {
   fmt.Println(value)
}

func main() {
   x := 10
   defer function(x)
   x = 20
   defer function(x)
}

defer内变量的值是何时确定的? (补充2)

package main

import (
   "fmt"
)

func main() {
   x := 10
   defer func() {
      fmt.Println(x)
   }()
   x = 20
   defer func() {
      fmt.Println(x)
   }()
}

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我爱golang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值