iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Go语言中延迟执行语句是哪个
  • 566
分享到

Go语言中延迟执行语句是哪个

2023-07-04 23:07:16 566人浏览 独家记忆
摘要

这篇“Go语言中延迟执行语句是哪个”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Go语言中延迟执行语句是哪个”文章吧。在Go

这篇“Go语言中延迟执行语句是哪个”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Go语言中延迟执行语句是哪个”文章吧。

在Go语言中,延迟执行语句是defer语句,语法“defer 任意语句”。defer语句会将其后面跟随的语句进行延迟处理,在defer归属的函数即将返回时,将延迟处理的语句按defer的逆序进行执行;也就是说,先被defer的语句最后被执行,最后被defer的语句,最先被执行。

Go 语言中的延迟执行语句(defer语句)

Go语言中存在一种延迟执行的语句,由defer关键字标识。

defer 关键字会将其后面跟随的语句进行延迟处理,在 defer 归属的函数即将返回时,将延迟处理的语句按 defer 的逆序进行执行,也就是说,先被 defer 的语句最后被执行,最后被 defer 的语句,最先被执行。

格式如下:

defer 任意语句

defer后的语句不会被马上执行,在defer所属的函数即将返回时,函数体中的所有defer语句将会按出现的顺序被逆序执行,即函数体中的最后一个defer语句最先被执行。

package mainimport "fmt"func main(){fmt.Println("start now")defer fmt.Println("这是第一句defer语句")defer fmt.Println("这是第二句defer语句")defer fmt.Println("这是第三句defer语句")fmt.Println("end")}

执行结果如下:

start nowend这是第三句defer语句这是第二句defer语句这是第一句defer语句

由于defer语句是在当前函数即将返回时被调用,所以defer常常被用来释放资源。

多个延迟执行语句的处理顺序

当有多个 defer 行为被注册时,它们会以逆序执行(类似栈,即后进先出),下面的代码是将一系列的数值打印语句按顺序延迟处理,如下所示:

package mainimport (    "fmt")func main() {    fmt.Println("defer begin")    // 将defer放入延迟调用栈    defer fmt.Println(1)    defer fmt.Println(2)    // 最后一个放入, 位于栈顶, 最先调用    defer fmt.Println(3)    fmt.Println("defer end")}

代码输出如下:

defer begindefer end321

结果分析如下:

  • 代码的延迟顺序与最终的执行顺序是反向的。

  • 延迟调用是在 defer 所在函数结束时进行,函数结束可以是正常返回时,也可以是发生宕机时。

使用延迟执行语句在函数退出时释放资源

处理业务或逻辑中涉及成对的操作是一件比较烦琐的事情,比如打开和关闭文件、接收请求和回复请求、加和解锁等。在这些操作中,最容易忽略的就是在每个函数退出处正确地释放和关闭资源。

defer 语句正好是在函数退出时执行的语句,所以使用 defer 能非常方便地处理资源释放问题。

1) 使用延迟并发解锁

在下面的例子中会在函数中并发使用 map,为防止竞态问题,使用 sync.Mutex 进行加锁,参见下面代码:

var (    // 一个演示用的映射    valueByKey      = make(map[string]int)    // 保证使用映射时的并发安全的互斥锁    valueByKeyGuard sync.Mutex)// 根据键读取值func readValue(key string) int {    // 对共享资源加锁    valueByKeyGuard.Lock()    // 取值    v := valueByKey[key]    // 对共享资源解锁    valueByKeyGuard.Unlock()    // 返回值    return v}

代码说明如下:

  • 第 3 行,实例化一个 map,键是 string 类型,值为 int。

  • 第 5 行,map 默认不是并发安全的,准备一个 sync.Mutex 互斥量保护 map 的访问。

  • 第 9 行,readValue() 函数给定一个键,从 map 中获得值后返回,该函数会在并发环境中使用,需要保证并发安全。

  • 第 11 行,使用互斥量加锁。

  • 第 13 行,从 map 中获取值。

  • 第 15 行,使用互斥量解锁。

  • 第 17 行,返回获取到的 map 值。

使用 defer 语句对上面的语句进行简化,参考下面的代码。

func readValue(key string) int {    valueByKeyGuard.Lock()       // defer后面的语句不会马上调用, 而是延迟到函数结束时调用    defer valueByKeyGuard.Unlock()    return valueByKey[key]}

上面的代码中第 6~8 行是对前面代码的修改和添加的代码,代码说明如下:

  • 第 6 行在互斥量加锁后,使用 defer 语句添加解锁,该语句不会马上执行,而是等 readValue() 函数返回时才会被执行。

  • 第 8 行,从 map 查询值并返回的过程中,与不使用互斥量的写法一样,对比上面的代码,这种写法更简单。

2) 使用延迟释放文件句柄

文件的操作需要经过打开文件、获取和操作文件资源、关闭资源几个过程,如果在操作完毕后不关闭文件资源,进程将一直无法释放文件资源,在下面的例子中将实现根据文件名获取文件大小的函数,函数中需要打开文件、获取文件大小和关闭文件等操作,由于每一步系统操作都需要进行错误处理,而每一步处理都会造成一次可能的退出,因此就需要在退出时释放资源,而我们需要密切关注在函数退出处正确地释放文件资源,参考下面的代码:

// 根据文件名查询其大小func fileSize(filename string) int64 {    // 根据文件名打开文件, 返回文件句柄和错误    f, err := os.Open(filename)    // 如果打开时发生错误, 返回文件大小为0    if err != nil {        return 0    }    // 取文件状态信息    info, err := f.Stat()       // 如果获取信息时发生错误, 关闭文件并返回文件大小为0    if err != nil {        f.Close()        return 0    }    // 取文件大小    size := info.Size()    // 关闭文件    f.Close()       // 返回文件大小    return size}

代码说明如下:

  • 第 2 行,定义获取文件大小的函数,返回值是 64 位的文件大小值。

  • 第 5 行,使用 os 包提供的函数 Open(),根据给定的文件名打开一个文件,并返回操作文件用的句柄和操作错误。

  • 第 8 行,如果打开的过程中发生错误,如文件没找到、文件被占用等,将返回文件大小为 0。

  • 第 13 行,此时文件句柄 f 可以正常使用,使用 f 的方法 Stat() 来获取文件的信息,获取信息时,可能也会发生错误。

  • 第 16~19 行对错误进行处理,此时文件是正常打开的,为了释放资源,必须要调用 f 的 Close() 方法来关闭文件,否则会发生资源泄露。

  • 第 22 行,获取文件大小。

  • 第 25 行,关闭文件、释放资源。

  • 第 28 行,返回获取到的文件大小。

在上面的例子中,第 25 行是对文件的关闭操作,下面使用 defer 对代码进行简化,代码如下:

func fileSize(filename string) int64 {    f, err := os.Open(filename)    if err != nil {        return 0    }    // 延迟调用Close, 此时Close不会被调用    defer f.Close()    info, err := f.Stat()    if err != nil {        // defer机制触发, 调用Close关闭文件        return 0    }    size := info.Size()    // defer机制触发, 调用Close关闭文件    return size}

代码中加粗部分为对比前面代码而修改的部分,代码说明如下:

  • 第 10 行,在文件正常打开后,使用 defer,将 f.Close() 延迟调用,注意,不能将这一句代码放在第 4 行空行处,一旦文件打开错误,f 将为空,在延迟语句触发时,将触发宕机错误。

  • 第 16 行和第 22 行,defer 后的语句(f.Close())将会在函数返回前被调用,自动释放资源。

以上就是关于“Go语言中延迟执行语句是哪个”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程网精选频道。

--结束END--

本文标题: Go语言中延迟执行语句是哪个

本文链接: https://www.lsjlt.com/news/348377.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Go语言中延迟执行语句是哪个
    这篇“Go语言中延迟执行语句是哪个”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Go语言中延迟执行语句是哪个”文章吧。在Go...
    99+
    2023-07-04
  • javascript的延迟语句是什么
    这篇文章主要讲解了“javascript的延迟语句是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“javascript的延迟语句是什么”吧! ...
    99+
    2024-04-02
  • GO语言延迟函数defer怎么使用
    今天小编给大家分享一下GO语言延迟函数defer怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。go语言中defer最...
    99+
    2023-07-05
  • 如何执行go语言
    这篇文章主要介绍“如何执行go语言”,在日常操作中,相信很多人在如何执行go语言问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何执行go语言”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!执行go语言的命...
    99+
    2023-07-04
  • Go语言函数的延迟调用(DeferredCode)详解
    目录基本功能示例一:延迟调用执行顺序示例二:多defer使用方法实例三:defer与局部变量、返回值的关系先解释一下这篇Blog延期的原因,本来已经准备好了全部内容,但是当我重新回顾...
    99+
    2024-04-02
  • C语言switch case语句的执行流程是什么
    C语言的switch case语句的执行流程如下:1. 首先,计算switch语句中的表达式的值。2. 根据表达式的值,程序将跳转到...
    99+
    2023-09-20
    C语言
  • try、finally与return语句在Java中哪个先执行
    今天就跟大家聊聊有关try、finally与return语句在Java中哪个先执行,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Demo1public class Test { p...
    99+
    2023-05-31
    java try finally
  • VB.NET中有哪些可执行语句
    今天就跟大家聊聊有关VB.NET中有哪些可执行语句,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。VB.NET可执行语句执行一项操作。它调用过程、分支到代码中的另一个位置、循环执行多个...
    99+
    2023-06-17
  • go语言中的return语句
    目录1、基本语法和说明2、函数的递归调用2.1基本介绍2.2递归调用入门3、总结1、基本语法和说明 在 Go 语言 中,跳转控制语句除了有 goto&n...
    99+
    2024-04-02
  • EntityFramework中执行sql语句
    一、为什么要在EF中执行SQL语句 使用EF操作数据库,可以避免写SQL语句,完成使用Linq实现,但为什么还要在EF中执行SQL语句呢。如果要写SQL语句,完全可以使用ADO.NE...
    99+
    2024-04-02
  • Go语言函数的延迟调用实例分析
    今天小编给大家分享一下Go语言函数的延迟调用实例分析的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。基本功能在以下这段代码中,...
    99+
    2023-07-02
  • php执行哪个语句删除整个数据库
    今天小编给大家分享一下php执行哪个语句删除整个数据库的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。首先,我们要知道如何删除...
    99+
    2023-07-05
  • MyBatis中SQL语句是怎么执行的
    MyBatis中的SQL语句执行流程大致如下: 配置文件:首先在配置文件(通常是mybatis-config.xml)中配置数据...
    99+
    2024-04-23
    MyBatis
  • ​mysql中语句执行顺序是什么
    这篇文章给大家分享的是有关mysql中语句执行顺序是什么的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。MySQL的语句一共分为11步,如下图所标注的那样,最先执行的总是FROM操...
    99+
    2024-04-02
  • GO语言中err接口及defer延迟异常处理分析
    目录err接口panic函数defer延迟defer与匿名函数结合使用recover防止程序中断err接口 Go语言引入了一个关于错误处理的标准模式,即error接口,它是Go语言内...
    99+
    2024-04-02
  • GO语言中err接口及defer延迟异常怎么处理
    这篇“GO语言中err接口及defer延迟异常怎么处理”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“GO语言中err接口及d...
    99+
    2023-06-30
  • go语言语法和哪个语言类似
    go语言语法和c语言类似。详细介绍:Go语言的语法受到了类C语言的影响,包括了分号作为语句结束符、花括号用于包裹代码块、以及函数定义和调用的格式。这使得有经验的C、C++、Java等语言的程序员可以很快上手Go语言。本教程操作系统:wind...
    99+
    2023-12-13
    go语言 Golang
  • Go语言中的DNS查询是否是异步执行的?
    《Go语言中的DNS查询是否是异步执行的?》 在网络编程中,DNS(Domain Name System)查询是一个十分常见的操作,它用于将域名转换为对应的IP地址。在Go语言中,我们...
    99+
    2024-04-02
  • Go语言中defer语句的用法
    可以用作一些资源的释放。 1.在一个函数内的defer执行顺序是先写的后执行,后写的先执行(遵循栈结构) func DeferTest1(){ defer fmt.Printl...
    99+
    2024-04-02
  • mysql查询语句中,是join先执行还是where先执行?
    在 MySQL 中,WHERE 子句会先于 JOIN 子句执行。 JOIN 子句用于连接两个或多个表,在 JOIN 子句中可以使用 ON 或 USING 子句来指定连接条件。 JOIN 子句会从两个表中返回符合连接条件的行,这些...
    99+
    2023-09-05
    mysql 数据库 sql mybatis
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作