GO: defer的使用场景、特性及使用

defer的使用场景

  • 释放资源(连接数据库之后defer等)
  • 记录日志
  • 加锁解锁

defer的三大特性

defer函数的传入参数在定义时就已经明确

func main() {
	i := 1
	defer fmt.Println(i)
	i++
	return
}

上面代码输出1,而不是2

defer函数是按照后进先出的顺序执行

func main() {
	for i := 1; i <= 5; i++ {
		defer fmt.Print(i)
	}
}

上面代码输出54321,而不是12345

defer函数可以读取和修改函数的命名返回值

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

func test() (i int) {
	defer func() {
		i++
	}()
	return 100
}

上面代码输出输出101,而不是100或者1

defer对有名返回值和无名返回值的影响

有名返回值即已经定义了函数的返回对象,无名返回值即只定义了函数的返回类型,没有定义返回对象

func f1() res int {
// 有名返回值,返回值为res
}

func f2() int {
// 无名返回值
}
package main

import "fmt"

func main()  {
	fmt.Println("f1 result: ", f1())
	fmt.Println("f2 result: ", f2())
}

func f1() int {
	var i int
	defer func() {
		i++
		fmt.Println("f11: ", i)
	}()

	defer func() {
		i++
		fmt.Println("f12: ", i)
	}()

	i = 1000
	return i
}

func f2() (i int) {
	defer func() {
		i++
		fmt.Println("f21: ", i)
	}()

	defer func() {
		i++
		fmt.Println("f22: ", i)
	}()

	i = 1000
	return i
}

返回结果为:

f12: 1001
f11: 1002
f1 result: 1000
f22: 1001
f21: 1002
f2 result: 1002

原理:
return会将返回值先保存起来。
对于无名返回值来说:返回值保存在临时对象中,defer无法处理这个临时对象
对于有名返回值来说:就保存在已命名的变量中,defer可以处理这个临时对象


defer匿名函数的各种情况

以下对defer的不同情况做讨论:

package main

import "fmt"

func main() {
	fmt.Println(f1())
	fmt.Println(f2())
	fmt.Println(f3_1())
	fmt.Println(f3_2())
	fmt.Println(f4())
	fmt.Println(f5())
}
func f1() int {
	x :=5
	defer func() {
		x++
	}()
	return x
}

假设无名返回变量为return_value
return x之后,return_value被赋予了x的值(5)
defer对x的改变不影响return_value
f1的返回结果为5


func f2() (x int) {
	defer func() {
		x++
	}()
	return 5
}

f2定义了返回的对象为x
return 5之后,x的值变为5
defer可以波及f2的返回值,故defer里面的x++就是返回值的自增
f2结果为6


func f3_1() (y int) {
	x :=5
	defer func() {
		x++
	}()
	return x
}

此处f3_1是有名返回值,返回参数的名字是y
return x之后将x的值(5)赋予给y,之后defer将f3_1内部的参数x做自增处理,x的值为6,但是y的值不变,是5
f3_1结果是5


func f3_2() (y int) {
	x :=5
	defer func() {
		y++
	}()
	return x
}

函数f3_2是有名返回值,返回参数的名字是y
return x的时候将f3_2函数内部定义变量x的值(5)赋予给了y,此时y的值是5
defer对y做自增操作,此时y的值变为6
f3_2返回结果是6


func f4() (x int) {          // 第一行: f4的有名返回参数x
	 defer func(x int) {     // 第二行: defer的输入形参x
	 	x++                  // 第三行: defer的输入形参x
	 }(x)                    // 第四行: 将f4的有名返回参数的值赋给defer匿名函数
	 return 5
}

f4函数返回有名返回值x
return 5之后,赋予了f4函数的返回参数x,给了5这个值
然后defer函数体后面接了(x),表示将f4返回参数x的值下发给了defer匿名函数
defer的匿名函数有自己的形参x(第二行的那个x),f4将自己返回参数的值给了defer的形参x
defer对自己的形参做自增操作并不会影响f4的返回参数。所以最终的返回结果还是5
f4结果为5

func f5() (x int) {
	x = 5
	defer func(x int) {
		x++
	}(x)
	return x
}

f5返回结果为5

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值