当前位置: 首页 > news >正文

Go defer用法

defer概览

  • defer是go语言里的一个关键字,在 函数内部使用;
  • defer关键字后面跟一个 函数或匿名函数;

defer用法

  • 执行一些资源的收尾工作,如 关闭数据库连接,关闭文件描述符,释放资源等等;
  • 结合recover()函数使用,防止函数内部的异常导致整个程序停止;
  • defer在遇到panic后,仍然会执行(defer语句要在panic之前编译),从而保证即使出错也能进行对应的错误处理;

函数中多个defer间存储方式及运行顺序

defer数据结构

type _defer struct {siz       int32started   boolopenDefer boolsp        uintptrpc        uintptrfn        *funcval_panic    *_paniclink      *_defer
}
  • _defer结构体中的link字段 指向下一个defer结构体地址的指针;
  • _defer结构体是 延迟调用链表中的一个元素,所有的结构体都是通过 link字段串联成链表;
  • 使用链表方式存储,
    在这里插入图片描述
  • 代码从上到下编译,遇到的 defer都会放到链表头部,后面执行的执行按照链表顺序从头到尾执行
  • defer编译及执行顺序 就是 栈的入栈出栈的顺序

defer必须要了解的特性

多defer执行顺序

结论

多defer执行顺序是 最后编译的先执行;

defer后面的函数的参数值的预计算

结论

defer在编译时,会对后面跟着的函数的参数值进行预计算;
也就是 编译器编译到此行时,会立刻确定 defer后面跟着函数的参数值,并且是 值传递方式,不是引用传递方式; 这样后续无论 这个参数对应的变量 值怎么改变,都和defer后面的函数无关;
所以 即使 参数 传了一个 函数,也会先计算函数的值 作为参数 进行值引用;

示例代码

defer后面跟的是系统自带的 fmt.Println函数

package mainimport "fmt"func A(v int) int {fmt.Println("A函数,入参为", v)v += 1return v
}func UseA(v int) int {defer fmt.Println("defer执行结果", A(v)) // A(v)的值:2    对应解析里的   "即使 参数 传了一个 函数,也会先计算函数的值 作为参数 进行值引用;  "defer fmt.Println("defer执行结果", v)    //v的值:1   对应解析里的   "后续无论 这个参数对应的变量 值怎么改变,都和defer后面的函数无关;"fmt.Println("UseA执行")v += 5fmt.Println("UseA执行return代码前的最后一行")return v
}func main() {fmt.Println("UseA执行结果", UseA(1)) //6return
}

代码执行结果

在这里插入图片描述

defer与return关键字执行顺序

结论

  • defer会在return关键字之后, 在返回给调用方前执行;

示例代码

package mainimport "fmt"func A(v int) int {fmt.Println("A函数,入参为", v)v += 1return v
}func UseOtherA(v int) int {defer fmt.Println("defer执行")return A(v)
}func main() {fmt.Println("UseOtherA执行结果",UseOtherA(1))return
}

代码执行结果

在这里插入图片描述

defer对 函数的返回值 是否定义变量名的影响

示例代码


package mainimport "fmt"func A(v int) int {fmt.Println("A函数,入参为", v)v += 1return v
}
func B(v int) (result int) {result = vdefer func() {result = A(v)}()return
}func C(v int) int {defer func() {v = A(v)}()return v
}
func main() {fmt.Println("B执行结果", B(1))fmt.Println("C执行结果", C(1))return
}

代码执行结果

在这里插入图片描述

结论

  • 定义返回值变量名 的函数,在返回给函数调用方前,这个变量的值都是可以修改的;
  • 未定义返回值变量名 的函数, 如上示例的C函数在 return语句执行时,其实是 将v变量 赋值给一个未定义名字的隐藏变量,来完成值传递, 所以后续对v变量的操作对 返回给函数调用结果无任何影响; 示意如下
    在这里插入图片描述

defer遇到panic执行情况

结论

  • panic触发后,函数内的后续代码不再执行,在panic之前编译的defer仍然会执行;

示例代码

package mainimport "fmt"func PanicT() {defer func() {if err := recover(); err != nil {fmt.Println("执行recover()方法,尝试恢复程序,错误内容为:", err)}}()defer fmt.Println("defer1")defer fmt.Println("defer2")panic("手动触发panic")defer fmt.Println("defer3,执行不到")
}func main() {PanicT()return
}

运行结果

在这里插入图片描述

defer中包含panic

结论

  • panic会被覆盖,只保留最新的panic;
  • 如: 函数中的panic会被defer的panic覆盖;
  • 如: 多个defer都有panic,只有最后执行的defer的panic会保留;
  • 其实 defer 后面也是普通函数,那么普通函数遇到panic就会停止运行,执行后续defer的函数;

代码示例


package mainimport "fmt"func PanicMany() {defer func() {if err := recover(); err != nil {fmt.Println("执行recover()方法,尝试恢复程序,错误内容为:", err)}}()defer func() {fmt.Println("defer1执行")panic("defer1手动触发panic")fmt.Println("defer1执行不到此处")}()defer func() {fmt.Println("defer2执行")panic("defer2手动触发panic")fmt.Println("defer2执行不到此处")}()panic("手动触发panic")defer fmt.Println("defer3,执行不到")
}func main() {PanicMany()return
}

代码执行结果

在这里插入图片描述

知识点训练

func main() {fmt.Println(test1())fmt.Println(test2())fmt.Println(test3())fmt.Println(test4())
}
func test1() (v int) {defer fmt.Println(v) //0return v             //0
}func test2() (v int) {defer func() {fmt.Println(v) //3}()return 3 //3
}func test3() (v int) {defer func() {fmt.Println(v)}() //4defer fmt.Println(v)                    //0defer func(v int) { fmt.Println(v) }(v) //0v = 3return 4 //4
}func test4() (v int) {defer func(n int) {fmt.Println(n) //0}(v)return 5 //5
}

总结

  • 对于defer执行结果的准确预测, 要了解函数的参数传递方式,函数的返回值是否定义变量名时 编译器的执行过程 等额外的知识点;
  • defer代码编写时经常遇到,常用于 异常捕捉,资源释放等收尾工作;

相关文章:

Go defer用法

defer概览 defer是go语言里的一个关键字,在 函数内部使用;defer关键字后面跟一个 函数或匿名函数; defer用法 执行一些资源的收尾工作,如 关闭数据库连接,关闭文件描述符,释放资源等等;结合recover()函数使用,防止函数内部的异常导致整个程序停止;defer在遇到panic后,仍然会…...

产地证是什么,主要作用有哪些?

产地证是什么,主要作用有哪些?最近一个客户问我,产地证是什么,主要作用有哪些?今天就来扒拉扒拉这个问题,其实很简单~通俗一点的讲,产地证是货物原产地的证明文件之一,主要用于国外清…...

王道计算机网络课代表 - 考研计算机 第一章 计算机网络体系结构 究极精华总结笔记

本篇博客是考研期间学习王道课程 传送门 的笔记,以及一整年里对 计算机网络 知识点的理解的总结。希望对新一届的计算机考研人提供帮助!!! 关于对 “计算机网络体系结构” 章节知识点总结的十分全面,涵括了《计算机网络…...

数据处理 |遍历所有文件夹及子目录文件夹方法总结与实例代码详解

深度学习中不可避免的数据预处理~1. glob.glob()方法 2. pathlib中的Path方法3. os.walk()方法1. glob.glob()方法 语法glob.glob(pathname)(多指定文件类型,查找jpg,png,txt,json等)缺点:查找文件较慢2. 路径操作库pathlib中的Pa…...

ProtoEditor - 如何在Unity中实现一个Protobuf通信协议类编辑器

文章目录简介Protobuf 语法规则Proto Editor实现创建窗口定义类、字段增删类编辑字段导入、导出Json文件生成.proto文件生成.bat文件简介 在Socket网络编程中,假如使用Protobuf作为网络通信协议,需要了解Protobuf语法规则、编写.proto文件并通过编译指令…...

2022 OpenCV Spatial AI大赛前三名项目分享,开源、上手即用,优化了OAK智能双目相机的深度效果。

编辑:OAK中国 首发:oakchina.cn 喜欢的话,请多多👍⭐️✍ 内容可能会不定期更新,官网内容都是最新的,请查看首发地址链接。 ▌前言 Hello,大家好,这里是OAK中国,我是助手…...

Android 蓝牙开发——HCI log 分析(二十)

HCI log 是用来分析蓝牙设备之间的交互行为是否符合预期,是否符合蓝牙规范。对于蓝牙开发者来说,通过 HCI log 可以帮助我们更好地分析问题,理解蓝牙协议。 一、抓取HCI log 1、手机抓取HCI log 在开发者选项中打开启用蓝牙HCI信息收集日志开关,Android系统就开始自动地收…...

flask入门-4.项目实战

4. 项目实战1 1. 问答平台项目结构搭建 项目结构 config.py hostname "127.0.0.1" port 3306 username "root" password "root"database "flask_qa"# 在 app.config 中设置连接数据库的信息 SQLALCHEMY_DATABASE_URI f"…...

java 1(概要、变量与运算符)

java ——概要、变量与运算符 ✍作者:电子科大不知名程序员 🌲专栏:java学习指导 各位读者如果觉得博主写的不错,请诸位多多支持;如果有错误的地方,欢迎在评论区指出 目录java ——概要、变量与运算符命令行…...

​力扣解法汇总2363. 合并相似的物品

目录链接: 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目: https://github.com/September26/java-algorithms 原题链接:力扣 描述: 给你两个二维整数数组 items1 和 items2 ,表示两个物品集合。每个数…...

2022年终总结-找回初心

和“那个夏天”群聊的几位死党聊完天后,发现自己已经忘了初心2年有余了,也是这次聊天让我重新燃起了要继续努力奋斗的想法。那就说一说2022年我过得如何吧。2022年过完春节刚来公司的几天就传来了一个好消息,我涨薪了。在没有涨薪之前私下有时…...

Allegro如何打开或者关闭DFA规则设置操作指导

Allegro如何打开或者关闭DFA规则设置操作指导 在用Allegro做PCB布局的时候,器件与器件之间的DFA规则可以避免器件出现装配问题。如下图 当DFA规则设置好之后,如何打开或者关闭规则,具体操作如下 点击Setup点击Constraints...

kind kubernetes 集群内如何通过 helm 部署定制化 Prometheus-Operator?

文章目录1. Prometheus 简介2. Prometheus 优势3. Prometheus 架构图4. Prometheus-Operator 简介5. Prometheus-Operator 架构图6. 环境准备7. Kind 部署 Kubernetes7.1 安装 Ingress-nginx 组件7.2 安装 Metric Server 组件8. helm 快速安装 Prometheus-Operator9. 定制 Prom…...

流媒体付服务器 ZLMediaKit 学习记录

1.官方github:ZLMediaKit 依赖于 media-server 库 #国内用户推荐从同步镜像网站gitee下载 git clone --depth 1 https://gitee.com/xia-chu/ZLMediaKit cd ZLMediaKit #千万不要忘记执行这句命令 git submodule update --init 之后 cd ZLMediaKit mkdir build…...

2023年了还不会写软件测试简历吗,那就来看这里吧,怎么样才能更容易让HR看到你的简历

作为软件测试的从业者,面试或者被面试都是常有的事。 可是不管怎样,和简历有着理不清的关系,面试官要通过简历了解面试者的基本信息、过往经历等。 面试者希望通过简历把自己最好的一面体现给面试官,所以在这场博弈中&#xff0…...

第四阶段08-基于element-ui的vue2.0脚手架(续)

42. VUE脚手架项目嵌套路由 在配置路由&#xff08;配置/src/router/index.js&#xff09;时&#xff0c;如果配置的路由对象是routes常量的直接数组元素&#xff0c;则此路由配置的视图会显示在App.vue的<router-view/>中。 在设计视图时&#xff0c;可能会出现<ro…...

数据库设计规范

三范式首先&#xff0c;设计数据库&#xff0c;要尽可能的满足三范式&#xff0c;遵循三范式开发会减少数据冗余、提升系统可扩展性和查询性能。第一范式的目标是确保每列的原子性如果每列都是不可再分的最小数据单元&#xff08;也称为最小的原子单元&#xff09;&#xff0c;…...

深入浅出PaddlePaddle函数——paddle.Tensor

分类目录&#xff1a;《深入浅出PaddlePaddle函数》总目录 Tensor是Paddle中最为基础的数据结构&#xff0c;有几种创建Tensor的不同方式&#xff1a; 用预先存在的数据创建1个Tensor&#xff0c;请参考paddle.to_tensor创建一个指定shape的Tensor&#xff0c;请参考paddle.on…...

docker删除已停止的容器

一、docker删除已停止的容器 1、根据容器的状态&#xff0c;删除Exited状态的容器 先停止容器、再删除镜像中的容器、最后删除none的镜像。执行命令如下&#xff1a; docker stop $(docker ps -a | grep "Exited" | awk {print $1 }) #停止容器 docker rm $(docke…...

JS#1 引入方式和基础语法

JavaScript(JS)是一门跨平台, 面向对象的脚本语言, 来控制网页行为的, 它能够是网页可交互一. 引入方式内部脚本与外部脚本内部脚本: 将JS代码定义在HTML页面中外部脚本: 将JS代码定义在外部JS文件中, 然后引入到HTML页面中注意: 在HTML中,JS代码必须位于<script></sc…...

面了一个测试工程师,明显感觉他背了很多面试题...

最近有朋友去字节面试&#xff0c;面试前后进行了20天左右&#xff0c;包含4轮电话面试、1轮笔试、1轮主管视频面试、1轮hr视频面试。 据他所说&#xff0c;80%的人都会栽在第一轮面试&#xff0c;要不是他面试前做足准备&#xff0c;估计都坚持不完后面几轮面试。 其实&…...

C#生成缩略图

using System;using System.Collections.Generic;using System.Drawing;using System.Drawing.Drawing2D;using System.Drawing.Imaging;using System.Text;namespace learun.util{public enum ThumbnailMode{/// <summary>/// 指定宽度&#xff0c;高度按照比例缩放/// …...

算法 # SimHash 算法:文本相似度、文本去重、海量文本快速查询

SimHash SimHash 是 Google 发明的海量网页去重的高效算法,将原始的文本映射为 64 位的二进制串,然后通过比较二进制的差异进而表示原始文本内容的差异。 传统的 Hash 算法只负责将原始内容尽量均匀随机地映射为一个 hash 值,原理上相当于伪随机数产生算法。SimHash 本身属…...

Java程序设计-JSP程序设计-SSM校园二手交易系统

摘 要 网络的广泛应用给生活带来了十分的便利。所以把二手物品交易管理与现在网络相结合&#xff0c;利用java技术建设二手物品交易系统&#xff0c;实现二手物品交易的信息化。则对于进一步提高二手物品交易管理发展&#xff0c;丰富二手物品交易管理经验能起到不少的促进作用…...

springBoot 消息转换器和自定义消息转换器

public interface HttpMessageConverter<T> {/*** 能否以指定的类读取*/boolean canRead(Class<?> clazz, Nullable MediaType mediaType);/*** 能否以指定的类写*/boolean canWrite(Class<?> clazz, Nullable MediaType mediaType);/*** 返回支持是消息转…...

机器学习笔记之流形模型——标准流模型基本介绍

机器学习笔记之流形模型——标准流模型基本介绍引言回顾&#xff1a;隐变量模型的缺陷标准流(Normalizing Flow\text{Normalizing Flow}Normalizing Flow)思想分布变换的推导过程引言 本节将介绍概率生成模型——标准流模型(Normalizing Flow\text{Normalizing Flow}Normalizi…...

MIT:只需一层RF传感器,就能为AR头显赋予“X光”穿透视力

近年来&#xff0c;AR在仓库、工厂等场景得到应用&#xff0c;比如GlobalFoundries、亚马逊、菜鸟裹裹就使用摄像头扫描定位货品&#xff0c;并使用AR来导航和标记。目前&#xff0c;这种方案主要基于视觉算法&#xff0c;因此仅能定位视线范围内的目标。然而&#xff0c;在一些…...

对 Dom 树的理解

什么是 DOM 从网络传给渲染引擎的 HTML 文件字节流是无法直接被渲染引擎理解的&#xff0c;所以要将其转化为渲染引擎能够理解的内部结构&#xff0c;这个结构就是 DOM。 DOM 提供了对 HTML 文档结构化的表述。 在渲染引擎中&#xff0c;DOM 有三个层面的作用&#xff1a; …...

电商搜索入门

一、搜索用途通常一个电商平台里面的商品&#xff0c;少则几十万多则上千万甚至上亿的sku&#xff0c;在这么多的商品中&#xff0c;如何让用户可以快速查找到自己想要的商品&#xff0c;那么就需要用到搜索功能来实现。通过分析数据发现&#xff0c;接近40%的点击率是直接通过…...

4.3.1初阶数据结构(C语言)(无头不循环单链表)

1.完整的单链表注释&#xff1a; #pragma once #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h>typedef int SLTDateType; // 重定义数据类型typedef struct SListNode // 定义结构体类型的节点 {SLTDateType data;str…...

wordpress文章编辑软件/开网店怎么开 新手无货源

4.讲讲JVM的类加载过程&&双亲委派模型。 5.谈谈Java的垃圾回收算法。 6.谈谈Java垃圾回收的触发条件。 7.synchronized和Lock的区别。 8.volatile的作⽤&#xff0c;为什么会出现变量读取不⼀致的情况&#xff0c;与 synchronized 的区别&#xff1f; 9.i 在多线程…...

网站开发用什么写/我有广告位怎么找客户

今天主要给大家带来一个小型公司的网络搭建&#xff0c;保证每一台计算机都可以访问www.ntd1711.com。 实验名称&#xff1a;小型公司网络的搭建 实验拓扑&#xff1a;实验目的&#xff1a;确保每个终端可以访问www.ntd1711.com&#xff08;192.168.30.88&#xff09;地址规划&…...

沧州手机网站建设/如何网页优化

2019独角兽企业重金招聘Python工程师标准>>> 摘要 本文介绍了contiki netstack的MAC层以下数据收发层次结构&#xff0c;并讨论如何移植新的无线器件做为contiki的无线收发器。 正文 contiki netstack的数据收发层级 Radio&#xff1a;主要完成物理层无线数据的收发…...

wordpress 调用摘要/竞价推广代运营企业

358 Lambda表达式练习2&#xff08;抽象方法带参无返回值&#xff09; 【练习2】 定义一个Chess接口&#xff0c;里面定义一个抽象方法&#xff1a;void play(String s)定义一个ChessDemo测试类&#xff0c;里面提供个方法 main&#xff0c;调用playChess(String s) playChes…...

北京网站制做的公司/seo在线优化工具 si

有需要学习交流的友人请加入交流群的咱们一起&#xff0c;有问题一起交流&#xff0c;一起进步&#xff01;前提是你是学技术的。感谢阅读&#xff01;点此加入该群​jq.qq.com当时的环境是没有使用框架的&#xff0c;直接在一个域名指向的目录下边新建目录之后访问该目录实现的…...

wordpress 小程序/百度联系方式人工客服

为什么80%的码农都做不了架构师&#xff1f;>>> JsonIgnoreProperties 此注解是类注解&#xff0c;作用是json序列化时将java bean中的一些属性忽略掉&#xff0c;序列化和反序列化都受影响。 JsonIgnore此注解用于属性或者方法上&#xff08;最好是属性上&#xf…...