学习于https://www.liwenzhou.com/posts/Go/function/的文章

1. defer的执行顺序类似于栈,“后进先出”,也就是最先defer的语句最后执行,而最后defer的最先执行

func main() {
defer fmt.Println("1")
defer fmt.Println("2")
defer fmt.Println("3")
} //控制台打印
3
2
1

2. defer和return的坑

首先return操作并不是原子操作,他分为2步:一是给返回值赋值,二是return返回值。如果函数中有defer的话,那么defer会被夹杂在2步中间,也就是先给返回值赋值,执行defer,return返回值

func main() {
fmt.Println("匿名返回:", a()) //5
fmt.Println("有名返回:", b()) //6
} // 匿名返回值
func a() int {
x := 5
defer func() {
x++
}()
return x
} // 有名返回值
func b() (x int) {
x = 5
defer func() {
x++
}()
return x
}

使用匿名返回函数,控制台打印的是5,这是执行return x时,首先定义 返回值=x(非同一个变量),然后执行defer x++,最后return返回值,而此时返回值已经=x,x++不会再影响返回值了,所以返回的是5。

使用有名返回时,就指定了返回值=x(同一个变量,内存地址相同),所以x++后,返回的值也++了。

3. defer注册要延迟执行的函数时该函数所有的参数都需要确定其值

func calc(index string, a, b int) int {
ret := a + b
fmt.Println(index, a, b, ret)
return ret
} func main() {
x := 1
y := 2
defer calc("AA", x, calc("A", x, y))
x = 10
defer calc("BB", x, calc("B", x, y))
y = 20
}

第一次注册defer calc("AA", x, calc("A", x, y))时,会执行里面的calc("A", x, y),此时x=1,y=2,所以先打印,

A 1 2 3

于是defer calc("AA", x, calc("A", x, y))中的参数被确定,是defer calc("AA", 1, 3)

接下来x=10,y没变,仍等于2,执行defer calc("BB", x, calc("B", x, y)),执行calc("B", x, y),打印

B 10 2 12

于是defer calc("BB", x, calc("B", x, y))中的参数被确定,是defer calc("BB", 10, 12)

然后按照defer顺序执行,先执行defer calc("BB", 10, 12),再执行defer calc("AA", 1, 3),所以打印

BB 10 12 22
AA 1 3 4

Golang defer使用的更多相关文章

  1. golang defer 延后执行什么

    对于golang的defer,我们已经知道,defer定义的语句可以延后到函数返回时执行. 经常用在文件的关闭,锁的释放等场景中.而且defer定义的语句即使遇到panic也会执行.这样,可以执行必要 ...

  2. golang defer的使用

    defer一般用于在函数结束时执行必要的处理工作.例如,关闭文件描述符,关闭网络连接等等. 函数中可以定义多个defer,执行的时候按照先进后出的顺序. defer定义的语句,即使遇到panic,也会 ...

  3. 拒绝滥用golang defer机制

    原文链接 : http://www.bugclosed.com/post/17 defer机制 go语言中的defer提供了在函数返回前执行操作的机制,在需要资源回收的场景非常方便易用(比如文件关闭, ...

  4. golang defer使用——资源关闭时候多用

    defer Go语言中有种不错的设计,即延迟(defer)语句,你可以在函数中添加多个defer语句.当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回.特别是当你在进行一些打开资源 ...

  5. golang defer那些坑

    defer以下几个特性,使用时需要关注下. 即时的参数传递 调用os.Exit()时defer不会被执行 defer与return的先后顺序 1.即时的参数传递 定义defer时传入的参数,是作为拷贝 ...

  6. golang defer 以及 函数栈和return

    defer 作为延迟函数存在,在函数执行结束时才会正式执行,一般用于资源释放等操作 参考一段代码https://mp.weixin.qq.com/s/yfH0CBnUBmH0oxfC2evKBA来分析 ...

  7. Golang入门教程(十三)延迟函数defer详解

    前言 大家都知道go语言的defer功能很强大,对于资源管理非常方便,但是如果没用好,也会有陷阱哦.Go 语言中延迟函数 defer 充当着 try...catch 的重任,使用起来也非常简便,然而在 ...

  8. 探究 Go 语言 defer 语句的三种机制

    Golang 的 1.13 版本 与 1.14 版本对 defer 进行了两次优化,使得 defer 的性能开销在大部分场景下都得到大幅降低,其中到底经历了什么原理? 这是因为这两个版本对 defer ...

  9. 【GoLang】panic defer recover 深入理解

    唉,只能说C程序员可以接受go的错误设计,相比java来说这个设计真的很差劲! 我认为知乎上说的比较中肯的: 1. The key lesson, however, is that errors ar ...

  10. golang中defer的使用规则

    转自个人博客chinazt.cc 在golang当中,defer代码块会在函数调用链表中增加一个函数调用.这个函数调用不是普通的函数调用,而是会在函数正常返回,也就是return之后添加一个函数调用. ...

随机推荐

  1. antd动态tree 自定义样式

    import React, { useEffect, useState } from 'react';import { Tree } from 'antd';import './index.less' ...

  2. SpringCloud之旅

    现在大部分公司的项目架构都选择了微服务,我们公司也不例外,那么什么是微服务呢?今天就来开启SpringCloud之旅! SpringCloud是基于SpringBoot的一整套的微服务架构.他提供了微 ...

  3. GDB使用详解

    来源:GDB使用详解 - 知乎 (zhihu.com) 1. 概述 ​ GDB 全称"GNU symbolic debugger",从名称上不难看出,它诞生于 GNU 计划(同时诞 ...

  4. unidbgrid显示图片

    column设置imageoptions属性,visible=true,设置width

  5. 03-Spring使用注解方式注入

    基于注解的DI注入 1.导包 环境搭建:导入aop包(spring-aop-4.1.6.RELEASE.jar) 2.创建类 3. 创建spring.xml配置文件(必须在src目录下) 该配置文件与 ...

  6. appium 遇到连接设备状态是offline

    1.查看连接手机设备 adb derivces 时,手机状态是offline状态(无法正常连接). 解决法: 1.adb kill-server 终止adb调试服务 2.adb start-serve ...

  7. AbstractRoutingDataSource - 动态数据源

    AbstractRoutingDataSource 类说明: (1)它的抽象方法 determineCurrentLookupKey() 决定使用哪个数据源. (2)项目启动时,先调用 setTarg ...

  8. MAC范洪攻击-macof

    macof 目的:攻击交换机的路由表,实现网络信息嗅探 macof是dsniff中的一个小工具 概要:交换机中存在着一个记录着MAC地址的表,为了完成数据的快速转发,这个表有着自动学习机制,学习后可以 ...

  9. Linux & 标准C语言学习 <DAY9_2>

    一.进程映像     程序:存储在磁盘上的可执行文件(二进制文件.脚本文件)     进程:正在系统中运行的程序     进程映像:进程的内存分布情况         text(代码段):       ...

  10. JOI 简单题选做

    就是把洛谷上评分为紫的题做了一下(汗) 前两道题没做出来,暴露了自己在 dp 上的短板. イベント巡り 2 一开始想到贪心,但发现我们只要选 \(k\) 个即可,所以可以尝试一些更劣但是编号更小的做法 ...