Go语言中defer语句的用法

可以用作一些资源的释放。

1.在一个函数内的defer执行顺序是先写的后执行,后写的先执行(遵循栈结构)

func DeferTest1(){
   defer fmt.Println("我是 defer1")
   defer fmt.Println("我是 defer2")
   fmt.Println("我是DeferTest1")
   fmt.Println("我是DeferTest2")
}

结果:

我是DeferTest1
我是DeferTest2
我是 defer2
我是 defer1

2.defer 执行语句的值和定义defer语句函数的关系

func DeferTest2(){
   i:= 0
   defer fmt.Printf("defer i=%d\t",i)
   for ;i<=10;i++{
      fmt.Printf("i=%d\t",i)
   }
   fmt.Println()
}

执行结果

i=0 i=1 i=2 i=3 i=4 i=5 i=6 i=7 i=8 i=9 i=10   
defer i=0

3.defer的原理

首先看下defer和return语句的区别,如下

可以看到 return 执行的时候 将结果x赋值给了返回值,然后执行了RET指令,而defer语句执行的时候,是在RET指令之前。所以这里注意一下。返回值和x的关系。如果x是一个值类型,这里是进行了拷贝的。可以看下下面几个例子:

func defer1() int {
  x := 1
  defer func() {
   x++<br data-filtered="filtered">  }()
  return x
}

func defer2() (x int) {
  defer func() {
    x++
  }()
  return 1
}

func defer3() (y int) {
  x := 1
  defer func() {
    x++
  }()
  return x
}

func defer4() (x int) {
  defer func(x int) {
    x++
    }(x)
    return 1
}

分别打印这几个方法的结果,返回值分别如下:

defer1: 1
defer2: 2
defer3: 1
defer4: 1

根据上面图上的解释:

  • ①defer执行之前,将x赋值给了返回值(这是一个值拷贝),然后修改x的值,对返回值是无影响的,所以返回的是1
  • ②返回值的名称就是x,此时defer执行前把x赋值为1,然后defer修改x的值, x被增加,故返回的是2
  • ③返回值名称是y,defer执行前,y被赋值为1,defer执行修改x对y无影响,返回也是1
  • ④返回值名称虽然是x,但是defer执行的func是一个带参数的函数,此时传入的参数x是一个值拷贝,作用域是内部,对于外部的x无影响,所以返回的也是1

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。如果你想了解更多相关内容请查看下面相关链接

(0)

相关推荐

  • 聊聊golang的defer的使用

    序 本文主要研究一下golang的defer defer return先赋值(对于命名返回值),然后执行defer,最后函数返回 defer函数调用的执行顺序与它们分别所属的defer语句的执行顺序相反 defer后面的表达式可以是func或者是method的调用,如果defer的函数为nil,则会panic 实例 实例1 // f returns 42 func f() (result int) { defer func() { // result is accessed after it w

  • golang中defer的基本使用教程

    目录 前言 1.什么是defer 2.defer的特点 3.defer什么时间执行 4.defer常见的坑 1.输出是多少? 2.输出多少 3.输出多少 4.输出什么 总结 前言 第一次看go基础语法的时候,用使用到了defer.但是一直不知道它到底是什么,有什么用途.这几天通过查询.学习.算是对defer有了一点浅显的认识. 1.什么是defer defer是go中一种延迟调用机制,defer后面的函数只有在当前函数执行完毕后才能执行,通常用于释放资源. 2.defer的特点 defer遵循先

  • Golang的关键字defer的使用方法

    目录 核心思想 defer链 源码分析 优化 核心思想 在defer出现的地方插入了指令CALL runtime.deferproc,在函数返回的地方插入了CALL runtime.deferreturn.goroutine的控制结构中,有一张表记录defer,调用runtime.deferproc时会将需要defer的表达式记录在表中,而在调用runtime.deferreturn的时候,则会依次从defer表中“出栈”并执行 如果有多个defer,调用顺序类似栈,越后面的defer表达式越先

  • Go程序员踩过的defer坑错误处理

    目录 前言 一.简单的例子 二.一定不要在 for 循环中使用 defer 语句 三.定义函数时就不要使用命名返回值 四.defer 表达式的函数如果在 panic 后面,则这个函数无法被执行. 五.执行顺序 五.捕获异常执行顺序 六.函数执行顺序 七.外部函数捕获异常执行顺序 八.recover 的返回值问题 前言 先声明:我被坑过. 之前写 Go 专栏时,写过一篇文章:Go 专栏|错误处理:defer,panic 和 recover.有小伙伴留言说:道理都懂,但还是不知道怎么用,而且还总出现

  • Golang之defer 延迟调用操作

    前言 defer语句被用于预定对一个函数的调用.我们把这类被defer语句调用的函数称为延迟函数.而defer 延迟语句在其他编程语言里好像没有见到.应该是属于 Go 语言里的独有的关键字.但用法类似于面向对象编程语言 Java 和 C# 的 finally 语句块. 下面对defer进行介绍. defer特性 1. 关键字 defer 用于注册延迟调用. 2. 这些调用直到 return 前才被执.因此,可以用来做资源清理. 3. 多个defer语句,按先进后出的方式执行. 1.延迟调用 用法

  • Go中defer使用场景及注意事项

    目录 1. 简介 1.1 使用场景 1.2 注意事项 2. defer 数据结构 3. 执行机制 3.1 栈上分配 3.2 开放编码 4. 参考 1. 简介 defer 会在当前函数返回前执行传入的函数,它会经常被用于关闭文件描述符.关闭数据库连接以及解锁资源. 理解这句话主要在三个方面: 当前函数 返回前执行,当然函数可能没有返回值 传入的函数,即 defer 关键值后面跟的是一个函数,包括普通函数如(fmt.Println), 也可以是匿名函数 func() 1.1 使用场景 使用 defe

  • Go语言defer语句的三种机制整理

    Golang 的 1.13 版本 与 1.14 版本对 defer 进行了两次优化,使得 defer 的性能开销在大部分场景下都得到大幅降低,其中到底经历了什么原理? 这是因为这两个版本对 defer 各加入了一项新的机制,使得 defer 语句在编译时,编译器会根据不同版本与情况,对每个 defer 选择不同的机制,以更轻量的方式运行调用. 堆上分配 在 Golang 1.13 之前的版本中,所有 defer 都是在堆上分配,该机制在编译时会进行两个步骤: 在 defer 语句的位置插入 ru

  • Go defer 原理和源码剖析(推荐)

    目录 1. 编译器编译 defer 过程 2. defer 传递参数 3. 执行多条 defer 4. defer 和 return 运行顺序 Go 语言中有一个非常有用的保留字 defer,它可以调用一个函数,该函数的执行被推迟到包裹它的函数返回时执行. defer 语句调用的函数,要么是因为包裹它的函数执行了 return 语句,到达了函数体的末端,要么是因为对应的 goroutine 发生了 panic. 在实际的 go 语言程序中,defer 语句可以代替其它语言中 try-catch-

  • Golang 的defer执行规则说明

    defer介绍 defer是golang的一个特色功能,被称为"延迟调用函数".当外部函数返回后执行defer.类似于其他语言的 try- catch - finally- 中的finally,当然差别还是明显的. 在使用defer之前我们应该多了解defer的特性,这样才能避免使用上的误区. 1. 最简单的defer func test(){ defer func(){ fmt.Println("defer") }() //todo //... return //

  • Go语言中defer语句的用法

    可以用作一些资源的释放. 1.在一个函数内的defer执行顺序是先写的后执行,后写的先执行(遵循栈结构) func DeferTest1(){ defer fmt.Println("我是 defer1") defer fmt.Println("我是 defer2") fmt.Println("我是DeferTest1") fmt.Println("我是DeferTest2") } 结果: 我是DeferTest1我是Defer

  • C语言中switch语句基本用法实例

    目录 switch语句: switch语句的基本格式 C语言switch语句用法 补充:用switch来给成绩等级 总结 switch语句: 实际生活中,需要做出很多选择,大家都知道做选择可以使用if语句,但是如果选择太多,if语句使用起来就会很繁琐,这个时候就需要一个能将代码简化的语句,也就是我们今天的主角switch语句. switch语句是一个多分支选择语句,并且可以支持嵌套. switch语句的基本格式 switch(表达式){case 常量1:语句1case 常量2:语句2defaul

  • go语言中if语句用法实例

    本文实例讲述了go语言中if语句用法.分享给大家供大家参考.具体分析如下: if 语句看起来跟 C 或者 Java 中的一样,除了没有了 ( ) 之外(甚至强制不能使用它们),而 { } 是必须的. 复制代码 代码如下: package main import (     "fmt"     "math" ) func sqrt(x float64) string {     if x < 0 {         return sqrt(-x) + "

  • Go语言中Select语句用法实例

    本文实例讲述了Go语言中Select语句用法.分享给大家供大家参考.具体分析如下: select 语句使得一个 goroutine 在多个通讯操作上等待. select 会阻塞,直到条件分支中的某个可以继续执行,这时就会执行那个条件分支.当多个都准备好的时候,会随机选择一个. 复制代码 代码如下: package main import "fmt" func fibonacci(c, quit chan int) {         x, y := 1, 1         for {

  • C++语言中std::array的用法小结(神器用法)

    摘要:在这篇文章里,将从各个角度介绍下std::array的用法,希望能带来一些启发. td::array是在C++11标准中增加的STL容器,它的设计目的是提供与原生数组类似的功能与性能.也正因此,使得std::array有很多与其他容器不同的特殊之处,比如:std::array的元素是直接存放在实例内部,而不是在堆上分配空间:std::array的大小必须在编译期确定:std::array的构造函数.析构函数和赋值操作符都是编译器隐式声明的--这让很多用惯了std::vector这类容器的程

  • 浅析Go语言中Channel的各种用法

    目录 Go语言基础四 if定义 单层if语法格式 语法警告 多层if语法格式 Switch定义 Type Switch Select定义 Select语句注意事项 Select用法补充 退出 判断Channel状态 Go语言基础四 今天我们要来学习if语句,也就是大家口中的判断语句,我们首先来看一下if语句的定义 if定义 条件语句需要开发者通过指定一个或多个条件,并通过测试条件是否为 true 来决定是否执行指定语句,并在条件为 false 的情况在执行另外的语句.相信读者看到这儿,也是云里雾

  • C语言中memcpy 函数的用法详解

    C语言中memcpy 函数的用法详解 memcpy(内存拷贝函数) c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中. void* memcpy(void* destination, const void* source, size_t num); void* dest 目标内存 const void* src 源内存 size_t num 字节个数 库中实现的memcpy函数 struct { ch

  • C语言中qsort函数的用法实例详解

    C语言中qsort函数的用法实例详解 快速排序是一种用的最多的排序算法,在C语言的标准库中也有快速排序的函数,下面说一下详细用法. qsort函数包含在<stdlib.h>中 qsort函数声明如下: void qsort(void * base,size_t nmemb,size_t size ,int(*compar)(const void *,const void *)); 参数说明: base,要排序的数组 nmemb,数组中元素的数目 size,每个数组元素占用的内存空间,可使用si

  • C语言中do-while语句的2种写法示例

    while循环和for循环都是入口条件循环,即在循环的每次迭代之前检查测试条件,所以有可能根本不执行循环体中的内容.C语言还有出口条件循环(exit-condition loop),即在循环的每次迭代之后检查测试条件,这保证了至少执行循环体中的内容一次.这种循环被称为do while循环. 看下面的例子: #include <stdio.h> int main(void) { const int secret_code = 13; int code_entered; do { printf(&

  • C语言中if语句加大括号和不加大括号的区别介绍

    首先来回顾以下if语句 if(表达式1){     语句1     语句2     --   } 如果表示条件的逻辑表达式的结果不是0,那么就执行后面跟着的这对大括号内的语句: 否则就跳过不执行 继续下面的其他语句. 但是if语句还有一种形式可以不用{}. 举个栗子: if(a > b) a += b + 10; if语句这一行结束的时候并没有表示语句结束的";",而后面的赋值语句写在if的下一行,而且缩进了,在这一行结束的时候有一个分号. 表明这条赋值语句是if语句的一部分,i

随机推荐