首页 > 其他分享 >go的defer机制

go的defer机制

时间:2024-08-22 08:54:51浏览次数:12  
标签:defer return 函数 func go 返回值 机制 执行

defer的底层机制

为栈操作,栈是一个先进后出的数据结构

func main() {
    fmt.Println("reciprocal")

    for i := 0; i < 10; i++ {
        defer fmt.Println(i)
    }
}

运行结果
reciprocal
9
8
7
6
5
4
3
2
1
0

defer拷贝机制

以下已经发生压栈发生值拷贝数据不再会发生变化

func test() int {
	var i = 1
	defer func(i int) {
		fmt.Println("数据压栈已压栈数据不会在发生变化", i)
	}(i)
	i++
	return i
}

运行结果

数据压栈已压栈数据不会在发生变化 1

函数返回值 2

deferreturn的返回时机(执行顺序)

根据defer内的变量为匿名函数,还是命名函数。函数的返回数据会有差距

1. 计算并赋值返回值

• 对于匿名返回值的函数,return 语句先会计算并生成返回值,并将其赋值给一个临时变量。

• 对于命名返回值的函数,return 语句会将结果赋值给命名的返回变量,这个变量在函数开始时就已经声明。

2. 执行 defer 语句

• defer 语句中的函数在 return 语句执行后被调用,但它们的执行顺序是后进先出 (Last In First Out, LIFO) 的。

• defer 函数可以操作命名返回值,从而可能修改最终的返回值。

3. 返回结果

• 在 defer 函数执行完后,返回最终的结果。

实践匿名函数

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

func Anonymous() int {
	var i int
	defer func() {
		i++
		fmt.Println("defer2 value is ", i)
	}()

	defer func() {
		i++
		fmt.Println("defer1 in value is ", i)
	}()

	return i
}

结果

defer1 in value is  1

defer2 value is  2

0

执行过程

        1. 函数执行到 return i 时,i 的值是 0。

        2. 执行 defer 语句,先执行 defer1,然后执行 defer2,此时 i 变为 2,但 return 的返回值已                固定为 0。

        3. 最终返回值为 0。

实践命名返回值的函数

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

func HasName() (j int) {
	defer func() {
		j++
		fmt.Println("defer2 in value", j)
	}()

	defer func() {
		j++
		fmt.Println("defer1 in value", j)
	}()

	return j
}

结果
defer1 in value 1
defer2 in value 2
2

执行过程

1. 函数执行到 return j 时,j 的初始值为 0。

2. 执行 defer 语句,先执行 defer1,j 变为 1,再执行 defer2,j 变为 2。

3. 最终返回值为 2,因为 defer 修改了命名返回值 j。

总结

匿名返回值函数:return 语句计算出返回值并存储在临时变量中,随后执行 defer 函数,但 defer 对返回值的修改不会影响最终返回值。

命名返回值函数:return 语句返回命名的返回变量,defer 函数能够修改这个变量,因此它会影响最终返回值。

defer 执行顺序的规则

1. defer 的参数在 defer 语句处计算。

2. defer 函数在函数返回时按照后进先出的顺序执行。

3. defer 函数可以读写返回函数的命名返回值。

defer 的使用场景:

1. 关闭资源

在处理文件、数据库连接、网络连接等需要关闭的资源时,defer 确保资源在使用完毕后被正确关闭,即使中间发生了错误。

2. 解锁资源

当使用 sync.Mutex 等锁机制时,defer 确保锁在临界区代码执行完毕后被解锁,从而避免死锁情况的发生。defer 释放分布式锁,防止死锁

3.记录日志或执行收尾工作

defer 可以用来记录函数的退出状态,或者在函数结束前执行一些收尾操作,例如日志记录或计时。

4. 处理错误和恢复(recover)

在可能会引发 panic 的代码中,defer 可以用来捕获和恢复错误,防止程序崩溃。

5. 清理临时状态

在函数内创建了一些临时状态或变量,需要在函数结束时清理时,defer 可以确保这些清理操作被执行。

引用

详解defer实现机制(附上三道面试题,我不信你们都能做对)

标签:defer,return,函数,func,go,返回值,机制,执行
From: https://blog.csdn.net/m0_61253599/article/details/141396457

相关文章

  • 第17章_反射机制
    该篇笔记,是因为想重新学一下SpringCloud和SpringCloudAlibaba框架,但是b站尚硅谷的最新课程,使用SpringBoot3作为,单体服务的框架,而SpringBoot3最低要求JDK17,所以必须要学一下JDK8-JDK17之间的新特性。本来只想看,宋红康老师课程的第18章JDK8-17新特性,但是觉得反射的API有点忘记,遂......
  • 【TCP】核心机制:滑动窗口、流量控制和拥塞控制
    文章目录滑动窗口窗口滑动滑动窗口丢包流量控制拥塞控制窗口大小变化过程滑动窗口有一类算法题,就是通过滑动窗口的思想来解决的,算法中的“滑动窗口”借鉴自TCP的滑动窗口TCP是要保证可靠传输的==>代价,降低了传输的效率(重传,确认重传等操作)TCP希望能在可靠传输......
  • 从零基础学Go(七)——Go的反射
    前言......
  • XSI机制的进程间通信
    XSI机制的进程间通信1、XSI介绍:什么是XSI:X/Open国际联盟有限公司是一个欧洲基金会,它的建立是为了向UNIX环境提供标准,XSI是X/OpenSystemInterface的缩写,也就是X/Open设计的系统接口。X/Open的主要的目标是促进对UNIX系统、接口、网络和应用的开放式系统协议的制定。它还促......
  • Study Plan For Algorithms - Part7
    1.罗马数字转整数题目链接:https://leetcode.cn/problems/roman-to-integer/罗马数字包含以下七种字符:I,V,X,L,C,D和M。字符数值I1V5X10L50C100D500M1000通常情况下,罗马数字中小的数字在大的数字的右边。但也存在六种特例:I可以放在......
  • SQL手工注入漏洞测试(MongoDB数据库)
    此次靶场地址为:墨者学院⼀.如下给出的源码...可以看到数据库查询的语句如下..构造回显测试... new_list.php?id=1'});return({title:'1',content:'2⼆.成功显示“1”和“2”。可以在此来显示想要查询的数据。接下来开始尝试构造payload查询当前数据库。通过回显观......
  • Gossip协议理解
    概述Gossip协议,又称epidemic协议,基于流行病传播方式的节点或进程之间信息交换的协议,在分布式系统中被广泛使用。在1987年8月由施乐-帕洛阿尔托研究中心发表ACM上的论文《EpidemicAlgorithmsforReplicatedDatabaseMaintenance》中被提出。原本用于分布式数据库中节点同步数......
  • MongoDB系列之一文总结索引
    概述分类索引的分类:按照索引包含的字段数量,可分为单键索引(单字段索引)和组合索引(联合索引、复合索引)按照索引字段的类型,可以分为主键索引和非主键索引按照索引节点与物理记录的对应方式来分,可以分为聚簇索引和非聚簇索引,其中聚簇索引是指索引节点上直接包含了数据记录,而后者......
  • MongoDB系列之WiredTiger引擎
    概述关系型数据库MySQL有InnoDB存储引擎,存储引擎很大程度上决定着数据库的性能。在MongoDB早期版本中,默认使用MMapV1存储引擎,其索引就是一个B-树(也称B树)。从MongoDB3.0开始引入WiredTiger(以下简称WT)存储引擎,在性能及稳定性上都有明显的提升。从MongoDB3.2开始,WT作为默认的引......
  • 2024-08-21:用go语言,给定一个从 0 开始索引的整数数组 nums 和一个整数 k,请设计一个算
    2024-08-21:用go语言,给定一个从0开始索引的整数数组nums和一个整数k,请设计一个算法来使得数组中的所有元素都大于或等于k,返回所需的最少操作次数。每次操作可以执行以下步骤:1.选择数组中最小的两个整数x和y。2.从数组中删除x和y。3.计算min(x,y)*2+max(x,y)......