每次学习并整理一个Golang的知识点,每天进步一点点。今天学习下go中的一个知识点:defer与返回值🤔

日省吾身

  1. 判断下面代码片段的输出结果?
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
func incrementA() int {
	var n int
	defer func() {
		n++
	}()
	return n
}

func incrementB() (m int) {
	defer func() {
		m++
	}()
	return m
}

func main() {
	fmt.Println(incrementA())
	fmt.Println(incrementB())
}
  • A. 0 0
  • B. 0 1
  • C. 1 0
  • D. 1 1

思考后看下方答案…

思考后看答案


答疑解惑

参考答案:

1. B incrementA()输出:0, incrementB()输出:1; 知识点: defer在匿名返回值和具名返回值中的不同表现;

  • 在之前的14问中我们有提到,Go 语言的 defer 一般在当前函数或者方法返回之前执行,一般用于调用一些收尾的函数,例如关闭文件描述符、关闭数据库连接以及解锁资源等;
  • 跟 Go 语言中大多数函数调用一样,都是采用值传递的;
  • 在之前的1问中,我们还提到当一个函数中同时存在多个defer语句时,defer语句的调用同栈一样,遵循先进后出的原则;
  • 这里涉及的知识点是:defer在匿名返回值和具名返回值函数中的表现不同; 为避免踩坑,要记住一点:return xxx 这一条语句不是一条原子指令!

以上述匿名函数举例,最后return的过程可以拆分成以下几步:

  1. 将n赋值给一个新的返回值nValue,nValue := n(可以理解成自动创建了一个新的返回值nValue)
  2. 然后检查是否有defer函数,如果有则执行
  3. 返回刚才创建的返回值:nValue

而具名返回值函数中,由于返回值在方法定义时已经被定义,所以不需要执行第1步赋值的过程,defer对返回值的修改也会被直接返回;

以上,你做对了吗?😊

其他相关答案或补充知识点,欢迎在评论区留言补充!

下期提问

  1. 写出下面代码片段的输出结果?
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
func f1() (result int) {
	defer func() {
		result++
	}()
	return 0
}

func f2() (result int) {
	t := 5
	defer func() {
		t = t + 5
	}()
	return t
}

func f3() (r int) {
	defer func(r int) {
		r = r + 5
	}(r)
	return 2
}

func main() {
	fmt.Println(f1())
	fmt.Println(f2())
	fmt.Println(f3())
}

答案及解析将在下期文章中给出,欢迎大家在评论区写出你的答案;独乐乐不如众乐乐,欢迎交流学习,互相进步。


欢迎转发和评论。更多优质原创文章,欢迎关注微信公众号“IYue爱月”或扫描下方二维码:

xujpxm_qrcode_gh