【Go 基础篇】Go语言中的defer关键字:延迟执行与资源管理

在这里插入图片描述

介绍

在Go语言中,defer 是一种用于延迟执行函数调用的关键字。它提供了一种简洁而强大的方式,用于在函数返回之前执行一些必要的清理操作或者释放资源。defer 的灵活性和易用性使得它在Go语言中广泛应用于资源管理、错误处理和代码结构优化等方面。🚀🚀🚀

本篇博客将详细介绍defer 关键字的使用方法、延迟执行的特性、常见应用场景以及一些注意事项。通过深入了解defer,您将能够写出更加清晰、可维护的Go代码,避免资源泄漏和错误处理的问题。

defer 的基本用法

基本语法

defer 关键字用于延迟执行一个函数调用,即使包含defer的函数在执行过程中发生了错误或提前返回,这个被defer的函数仍然会被执行。

func main() {
    defer fmt.Println("World")
    fmt.Println("Hello")
}
// 输出:
// Hello
// World

在上述示例中,fmt.Println("World") 函数会在 main() 函数返回前被执行,即使在Hello输出之后。

延迟执行的顺序

如果一个函数中有多个defer语句,它们会以先进后出的顺序被执行。也就是说,最后一个被defer的函数会最先被执行,依此类推。

func main() {
    defer fmt.Println("First")
    defer fmt.Println("Second")
    fmt.Println("Hello")
}
// 输出:
// Hello
// Second
// First

在上述示例中,First 会在 Second 之后被执行。🎈🎈🎈🎈🎈

defer 的应用场景

资源释放

一个重要的应用场景是在函数结束时释放资源,例如关闭文件、关闭数据库连接、释放内存等。使用defer能够确保资源在函数执行完毕时被释放,避免资源泄漏。

func readFile(filename string) ([]byte, error) {
    file, err := os.Open(filename)
    if err != nil {
        return nil, err
    }
    defer file.Close() // 确保在函数返回前关闭文件

    data, err := ioutil.ReadAll(file)
    if err != nil {
        return nil, err
    }
    return data, nil
}

在上述示例中,file.Close() 函数调用被放在了defer语句中,确保了文件在函数结束时被关闭。

错误处理

defer还可以用于错误处理,将错误处理逻辑从业务逻辑中分离出来,使代码更加清晰。通过在错误处理函数中使用defer,可以在函数返回前进行日志记录、统计等操作。

func handleError(err error) {
    if err != nil {
        fmt.Println("An error occurred:", err)
    }
}

func main() {
    defer handleError(recover()) // 在panic时执行错误处理
    panic("Oops, something went wrong!")
}
// 输出:
// An error occurred: Oops, something went wrong!

在上述示例中,handleError 函数会在 main() 函数中的panic发生时被执行。

性能优化

defer 语句的执行开销通常很小,但是在某些性能敏感的情况下,可能需要避免过多地使用defer。可以使用defer来延迟一些高开销的操作,以便在函数返回之前进行。

defer 的注意事项

参数求值时机

defer语句中,函数的参数在defer语句执行时就会被求值。这意味着如果函数参数包含了表达式,这些表达式会在defer语句执行时被计算,而不是在函数实际执行时。⭐⭐⭐⭐

func main() {
    i := 0
    defer fmt.Println(i) // 输出 0,不是 1
    i++
}

避免过度使用

虽然defer语句非常强大,但是过度使用它可能会使代码变得难以理解。应当遵循适度使用的原则,将defer用于清晰化代码、资源释放和错误处理等需要的地方。❀❀❀❀❀

总结

defer 关键字是Go语言中一个强大的工具,用于延迟执行函数调用,实现资源释放、错误处理和性能优化等功能。通过将需要延迟执行的操作放在defer语句中,可以保证这些操作会在函数返回前被执行,增加代码的可靠性和可维护性。同时,defer的应用场景包括资源管理、错误处理、性能优化等多个方面,使得它在Go语言中具有广泛的用途。

在使用defer时,需要注意参数求值时机和避免过度使用的问题,以保证代码的正确性和清晰性。通过合理地使用defer,您可以编写更加优雅和高效的Go代码,为项目开发提供更大的支持。🚀🚀🚀🚀🚀

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/90375.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis笔记——(狂神说)待续

Nosql概述 为什么要用NoSql? 1、单机mysql的年代:90年代,网站访问量小,很多使用静态网页html写的,服务器没压力。 当时瓶颈是:1)数据量太大一个机器放不下。2)数据的索引(BTree),一个机器内存也…

rabbitmq的优先级队列

在我们系统中有一个 订单催付 的场景,我们的客户在天猫下的订单 , 淘宝会及时将订单推送给我们,如果在用户设定的时间内未付款那么就会给用户推送一条短信提醒,很简单的一个功能对吧,但是,tianmao商家对我们来说&#…

数据工厂调研及结果展示

数据工厂 一、背景 在开发自测、测试迭代测试、产品验收的过程中,都需要各种各样的前置数据,大致分为如下几类: 账号(实名、权益等级、注册等) 货源(优货、急走、相似、一手、普通货源等) …

创建 github 项目,并自动化配置

一 新建项目 github 创建新项目,并自动化部署 二 github 到本地 三 自动化部署 配置docker 和 Jenkins文件 改 Jenkins 配置。 3.1 需要配置的文件 3.2 修改jenkinsfile 项目名称 如果要新项目,就修改里面的依赖和Jenkinsfile里面的project name 四 …

开源文库系统moredoc

什么是 moredoc ? moredoc 中文名 魔豆文库,是基于 golang 开发的类似百度文库、新浪爱问文库的开源文库系统,支持 TXT、PDF、EPUB、MOBI、Office 等格式文档的在线预览与管理,为 dochub 文库(github, gitee )的重构版…

⌈算法进阶⌋图论::拓扑排序(Topological Sorting)——快速理解到熟练运用

目录 一、原理 1. 引例:207.课程表 2. 应用场景 3. 代码思路 二、代码模板 三、练习 1、210.课程表Ⅱ🟢 2、2392.给定条件下构造举证🟡 3、310.最小高度树 🟡 一、原理 1. 引例:207.课程表 就如大学课程安排一样&…

Leaflet开发入门

Leaflet开发入门 开发环境配置Leaflet开发库开发移动端Hybrid App或移动Web App 开发环境配置 电子地图已经渗透到O2O、生活服务、出行等领域,传统的GIS也孕育着互联网基因。在国内互联网电子地图领域,百度地图和高德地图较为出色,天地图作为…

CSS中如何改变鼠标指针样式(cursor)?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ CSS中改变鼠标指针样式(cursor)⭐ 示例:⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅…

快速排序三种思路详解!

一、快速排序的介绍 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中 的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,…

CentOS7.9安装Java11

文章目录 Java11版本介绍安装步骤查看并卸载已有版本安装Java11最新版本配置生效 openjdk介绍 Java11版本介绍 Java 11是Java编程语言的一个重要版本,于2018年9月发布Java 11在语言特性、性能优化和安全性方面都有一些显著的改进,为Java开发者提供了更多…

minion在ubuntu上的搭建步骤

在Ubuntu上搭建MinIO可以按照以下步骤进行: 下载MinIO服务器二进制文件: 通过浏览器访问 https://min.io/download 或使用以下命令获取最新的MinIO二进制文件:wget https://dl.min.io/server/minio/release/linux-amd64/minio赋予二进制文件…

无人机精细化巡检方案制定:提高效率与准确性的关键

在当前技术日新月异的时代,无人机在多个领域的应用已成为行业标配。但如何制定出一套有效、细致的无人机巡检方案,确保其最大效能,成为许多组织与公司的核心议题。其中,复亚智能在此领域已展现出了卓越的实力与深入的见解。 1. 精…

最新SQLMap进阶技术

SQLMap进阶:参数讲解 (1)–level 5:探测等级。 参数“–level 5”指需要执行的测试等级,一共有5个等级(1~5级),可不加“level”,默认是1级。可以在xml/payloads.xml中看…

Flask入门一 ——虚拟环境及Flask安装

Flask入门一 ——虚拟环境及Flask安装 在大多数标准中,Flask都算是小型框架,小到可以称为“微框架”,但是并不意味着他比其他框架功能少。Flask自开发伊始就被设计为可扩展的框架。Flask具有一个包含基本服务的强健核心,其他功能…

element-ui table中使用type=‘selection‘ 实现禁用,勾选,默认选中不可修改 三种状态显示问题

element-ui table中使用type‘selection’ 实现禁用,勾选,默认选中不可修改 三种状态显示问题 实现效果 需求 1.status‘CheckOk 时 勾选框默认选中但不可修改勾选状态 2.status‘CheckFail 时 勾选框禁用 3.status‘ 时 勾选框可以勾选 实现思路 采…

Selenium 捕获 console logs (Java)

目录 启用日志记录功能 有时候在进行自动化测试的时候控制台输出会帮忙定位问题,所以捕获控制台输出就显得很重要了~ 以下以selenium 4为例: 我们可以使用driver.manage().logs().get(LogType.BROWSER)代码在Selenium中检索日志,该代码将返回…

Java单元测试 JUnit 5 快速上手

一、背景 什么是 JUnit 5?首先就得聊下 Java 单元测试框架 JUnit,它与另一个框架 TestNG 占据了 Java领域里单元测试框架的主要市场,其中 JUnit 有着较长的发展历史和不断演进的丰富功能,备受大多数 Java 开发者的青睐。 而说到…

LLM-chatgpt训练过程

流程简介 主要包含模型预训练和指令微调两个阶段 模型预训练&#xff1a;搜集海量的文本数据&#xff0c;无监督的训练自回归decoder&#xff1b; O T P ( O t < T ) O_TP(O_{t<T}) OT​P(Ot<T​)&#xff0c;损失函数CE loss指令微调&#xff1a;在输入文本中加入…

Windows命令行调用main函数

通常C/C的入口函数都是main函数&#xff0c;平常一般使用的原型都是 int main() ;但是&#xff0c;实际上&#xff0c;main函数也可以有参数 int main(intargc[ ,char*argv[] [,char*envp[] ] ] ); int wmain(intargc[ ,wchar_t*argv[] [,wchar_t*envp[] ] ] );//适用于这种带…

P1065 [NOIP2006 提高组] 作业调度方案

题目描述 我们现在要利用 m m m 台机器加工 n n n 个工件&#xff0c;每个工件都有 m m m 道工序&#xff0c;每道工序都在不同的指定的机器上完成。每个工件的每道工序都有指定的加工时间。 每个工件的每个工序称为一个操作&#xff0c;我们用记号 j-k 表示一个操作&…