首页 > 其他分享 >Golang基础--defer的用法

Golang基础--defer的用法

时间:2023-04-09 16:45:10浏览次数:33  
标签:语句 defer 函数 -- fmt Golang func 延迟

defer语句用于延迟函数的调用,每次defer都会把一个函数压入栈中,函数返回前再把延迟的函数取出执行。

三个示例:

import "fmt"

func main() {
    var init = 1
    defer fmt.Println(init)
    init = 2
}

输出1。延迟函数fmt.Println(aInt)的参数在defer语句出现时就已经确定了,所以无论后面如何修改 aInt变量都不会影响延迟函数。

eg2:

import "fmt"
func Print(array *[3]int) {
    for i := range array {
        fmt.Println(array[i])
    }
}

func DeferFuncArray() {
    var array = [3]int{
        1,
        2,
        3,
    }
    defer Print(&array)
    array[0] = 10
}
func main() {
    DeferFuncArray()
}

输出10、2、3三个值。延迟函数printArray()的参数在defer语句出现时就已经确定了,即数组的地 址,由于延迟函数执行时机是在return语句之前,所以对数组的最终修改值会被打印出来。

eg3:

import "fmt"

func deferFunc() (result int) {
    i := 1
    defer func() {
        result++
    }()
    return i
}

func main() {
    fmt.Println(deferFunc())
}

函数输出2。函数的return语句并不是原子的,实际执行分为设置返回值—>ret,defer语句实际执行在 返回前,即拥有defer的函数返回过程是:设置返回值—>执行defer—>ret。所以return语句先把result设置为i 的值,即1,defer语句中又把result递增1,所以最终返回2。

defer规则

  规则一:延迟函数的参数在defer语句出现时就已经确定

    对于指针类型参数,规则仍然适用,只不过延迟函数的参数是一个地址值,这种情况下,defer后面的语句对变量的修改可能会影响到延迟函数

  规则二:延迟函数执行按后进先出顺序执行,即先出现的defer最后执行

  规则三:延迟函数可能操作住函数的具名返回值

    定义defer函数,即住函数可能有返回值,返回值有没有名字没有关系,defer所作用的函数,即延迟函数可能会影响返回值

defer实现原理

  defer数据结构

  type _defer struct{

    sp  uintptr //函数栈指针

    pc  uintptr //函数计数器

    fn  *funcval //函数地址

    link  *_defer //指向自身结构的指针,用于链接多个defer

  }

  与函数不同的一点是它含有一个指针,可用于指向另一个defer,每个goroutine数据结构中实际上也有一个defer 指针,该指针指向一个defer的单链表,每次声明一个defer时就将defer插入到单链表表头,每次执行defer时就 从单链表表头取出一个defer执行。一个goroutine可能连续调用多个函数,defer添加过程跟上述一致,进入函数时添加defer,离开函数时取出defer,所以即便调用多个函数,也总是能保证defer是按照先进先出方式进心的

  

 

 

 

标签:语句,defer,函数,--,fmt,Golang,func,延迟
From: https://www.cnblogs.com/99kol/p/17300541.html

相关文章

  • docker 推送本地镜像到docker Hub仓库
    #chuyuan2022是dockerhub上的用户名,nginx_proxy_manager是仓库名dockerlogin-uchuyuan2022#输入密码dockercommit要推送的镜像ID新镜像名字nginx_proxy_manager#nginx_proxy_manager是dockerhub仓库的镜像名称dockertag新镜像名字nginx......
  • nginx配置文件及虚拟主机
    最小配置nginx.conf去掉注释字段后剩余的字段#工作进程数量,配置为对应cpu核数量效果最好worker_processes1;events{#每个worker进程能创建的链接数量,默认即可worker_connections1024;}http{#引入响应头的Content-Type值includemime.t......
  • 观《赛博浪客》有感
    Cyberpunk-Edgerunners,这是一部很刺激、很令人感动的动漫,十集五个小时就能看完。我是一个不喜欢被煽动情绪的人,希望作为情绪的掌控者。因此对于一部剧或者电影或者动漫,评价其为“令人感动的”对于我来说意味着非常深入地令我的内心跟着情节起伏。这里不说它讲了什么故事,让一个......
  • eeglab 下载超详细步骤(小白适用)
    eeg下载地址: https://eeglab.org/随便填一填~ 下载好了:(科学上网前提下+不用迅雷,浏览器自带下载器下载,好像要更快一点,大小为89.2M) ......
  • 人工智能概率算法-模拟神经元结构预测价格
    最近研究人工智能概率算法,想通过统计学的方式预测未来比较好的例子就是股票,历史数据很丰富输入端:4个参数(开盘价、最高价、最低价、收盘价)输出端:4个参数第二天(开盘价、最高价、最低价、收盘价)把价格从-10到+10,每次迭代0.1,分类成200个特征刚开始神经元的输入端不敏感,细胞核不......
  • 专网通信增速迅猛,5G轻量化核心网迎来机遇
    根据工信部最新的数据,截至2月底,国内5G基站总数达到了238.4万。5G基站占移动基站总数的比例,也提升至21.9%。不断增加的5G基站,带来了越来越完善的5G网络覆盖。这不仅让手机用户享受到了更好的网络体验,也加速了垂直行业用户落地5G的进程。截至目前,国内已经落地了超过50000个5G行业应用......
  • Metasploit高级技术【第一章】
    预计更新第一章Metasploit的使用和配置1.1安装和配置Metasploit1.2Metasploit的基础命令和选项1.3高级选项和配置第二章渗透测试的漏洞利用和攻击方法1.1渗透测试中常见的漏洞类型和利用方法1.2Metasploit的漏洞利用模块和选项1.3模块编写和自定义第三章Metasploit的提权......
  • macOS 13.3.1 (22E261)With OpenCore 0.9.2开发版 and winPE双引导分区原版镜像
    镜像特点原文来源于黑果魏叔官网,转载需注明出处。(下载请直接百度黑果魏叔)完全由黑果魏叔官方制作,针对各种机型进行默认配置,让黑苹果安装不再困难。系统镜像设置为双引导分区,全面去除clover引导分区(如有需要,可以自行直接替换opencore分区文件为clover引导文件)备注:此镜像仅适用与16g......
  • 源码共读 | 为 vite 项目自动添加 eslint 和 prettier
    前言Vite是一个用于现代JavaScript应用程序的快速、轻量级的构建工具,其设计目的是易于使用和适用于大型项目。Vite-pretty-lint是一个插件,可以在基于Vite的项目中安装和配置,以便在编写代码时能够自动对代码进行格式化和检查代码。这可以帮助开发人员在开发过程的早期捕获格......
  • canvas基础4
    canvas基础4一、图案//图案是用于填充和描画图形的重复图像。//要创建新图案,可以调用createPattern()方法并传入两个参数。letimage=newImage();image.src=star.png;pattern=context.createPattern(image,"repeat");//画一个矩形context.fillStyle=patte......