Golang defer 使用及面试常见的坑

前言

defer是Golang中一个常用的关键字,通常用来做一些收尾工作。比如开启了一个东西,就顺手defer中关闭。对于面试,defer也算一个高频考点,尤其是他的许多个坑,因此本文主要复习一下defer的用法

多个defer的执行顺序

通常来说,defer是在程序的最后才执行。当多个defer出现时,遵循 栈 的先入后出顺序执行。

前言

defer是Golang中一个常用的关键字,通常用来做一些收尾工作。比如开启了一个东西,就顺手defer中关闭。对于面试,defer也算一个高频考点,尤其是他的许多个坑,因此本文主要复习一下defer的用法

多个defer的执行顺序

通常来说,defer是在程序的最后才执行。当多个defer出现时,遵循 栈 的先入后出顺序执行。

在这里插入图片描述

deferreturn一起使用

关于deferreturn的执行顺序,普遍来说是先returndefer,可以参考此例。(直接cv一个,懒得写了)。

go 复制代码
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()
}


------------------------------------------------
原文作者:刘丹冰Aceld
转自链接:https://learnku.com/articles/42255
版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请保留以上作者信息和原文链接。
go 复制代码
执行结果
return func called
defer func called

此篇文章中是分了多点来概述此情况------

"知识点 2: defer 与 return 谁先谁后",

"知识点 3:函数的返回值初始化",

"知识点 4: 有名函数返回值遇见 defer 情况"

但我认为这样理解下来较为复杂,因此参考了此文,从return的角度来理解,将其归纳在一起。

return并不是原子操作,而是分为:赋值、返回 两个步骤。

加上defer,三者的执行时机则是:赋值、defer、return。

不带命名返回值

因此对应来看,对于"不带命名返回值"的情况,即func test() int这样的情况,由于return的值相当于是编译器自己新建的一个var tmp int,而defer中进行赋值操作则不会影响tmp,因此不影响返回值。

go 复制代码
package main

import "fmt"

func main() {
	t := test()
	fmt.Println(t)
}

func test() int { //无名返回
        i:=9
	defer func() {
		i++
		fmt.Println("defer1=", i)
	}()

	defer func() {
		i++
		fmt.Println("defer2=", i)
	}()

	return i
} 

作者:蓝色记忆
链接:https://juejin.cn/post/7095631673865273352
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

此例中,输出内容是:

go 复制代码
defer2= 10
defer1= 11
9 

可以理解为,系统var tmp int,这个tmp是需要返回的值,他是9。但是defer修改的是i,所以互不干涉。

有名返回值

对于有名返回值的情况,由于有名,所以没有了var tmp int这一步,defer中执行的修改会影响return的值,因此会影响。

defer配合panicrecover

参考此文

参考资源

https://learnku.com/articles/42255
https://juejin.cn/post/7095631673865273352
https://juejin.cn/post/7304183399885996067

deferreturn一起使用

关于deferreturn的执行顺序,普遍来说是先returndefer,可以参考此例。(直接cv一个,懒得写了)。

go 复制代码
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()
}


------------------------------------------------
原文作者:刘丹冰Aceld
转自链接:https://learnku.com/articles/42255
版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请保留以上作者信息和原文链接。
go 复制代码
执行结果
return func called
defer func called

此篇文章中是分了多点来概述此情况------

"知识点 2: defer 与 return 谁先谁后",

"知识点 3:函数的返回值初始化",

"知识点 4: 有名函数返回值遇见 defer 情况"

但我认为这样理解下来较为复杂,因此参考了此文,从return的角度来理解,将其归纳在一起。

return并不是原子操作,而是分为:赋值、返回 两个步骤。

加上defer,三者的执行时机则是:赋值、defer、return。

不带命名返回值

因此对应来看,对于"不带命名返回值"的情况,即func test() int这样的情况,由于return的值相当于是编译器自己新建的一个var tmp int,而defer中进行赋值操作则不会影响tmp,因此不影响返回值。

go 复制代码
package main

import "fmt"

func main() {
	t := test()
	fmt.Println(t)
}

func test() int { //无名返回
        i:=9
	defer func() {
		i++
		fmt.Println("defer1=", i)
	}()

	defer func() {
		i++
		fmt.Println("defer2=", i)
	}()

	return i
} 

作者:蓝色记忆
链接:https://juejin.cn/post/7095631673865273352
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

此例中,输出内容是:

go 复制代码
defer2= 10
defer1= 11
9 

可以理解为,系统var tmp int,这个tmp是需要返回的值,他是9。但是defer修改的是i,所以互不干涉。

有名返回值

对于有名返回值的情况,由于有名,所以没有了var tmp int这一步,defer中执行的修改会影响return的值,因此会影响。

defer配合panicrecover

参考此文

参考资源

https://learnku.com/articles/42255
https://juejin.cn/post/7095631673865273352
https://juejin.cn/post/7304183399885996067

相关推荐
程序猿小三2 分钟前
python uv的了解与使用
开发语言·python·uv
纯纯沙口2 分钟前
Qt—多线程基础
开发语言·qt
yxc_inspire5 分钟前
基于Qt的app开发第八天
开发语言·c++·qt
廖圣平6 分钟前
美团核销 第三方接口供应商 (含接口文档)
开发语言·数据库·php
sunsineq16 分钟前
[超级简单]讲解如何用PHP实现LINE Pay API!
开发语言·php·linepay
上海合宙LuatOS39 分钟前
全栈工程师实战手册:LuatOS日志系统开发指南!
java·开发语言·单片机·嵌入式硬件·物联网·php·硬件工程
多敲代码防脱发40 分钟前
导出导入Excel文件(详解-基于EasyExcel)
java·开发语言·jvm·数据库·mysql·excel
Asus.Blogs1 小时前
为什么 import _ “github.com/go-sql-driver/mysql“ 要导入但不使用?_ 是什么意思?
sql·golang·github
来自星星的坤1 小时前
深入理解 NumPy:Python 科学计算的基石
开发语言·python·numpy
小声读源码2 小时前
【技巧】使用UV创建python项目的开发环境
开发语言·python·uv·dify