defer使用语法

//defer后面必须是函数调用语句或方法调用语句,不能是其他语句,否则编译器会出错。
package main
import (
"fmt"
)
func foo(n int) int {
defer n++
//defer fmt.Println(n)
return n
}
func main() {
var i int = 100
foo(i)
}
# command-line-arguments
expression in defer must be function call
syntax error: unexpected ++ at end of statement

  

defer 语句的用途

含有 defer 语句的函数,会在该函数将要返回之前,调用另一个函数。

defer后面的函数在defer语句所在的函数执行结束的时候会被调用;

package main
import (
"fmt"
) type person struct {
firstName string
lastName string
} func (p person) fullName() {
fmt.Printf("%s %s",p.firstName,p.lastName)
} func main() {
p := person {
firstName: "John",
lastName: "Smith",
}
defer p.fullName()
fmt.Printf("Welcome ")
}

在上面的程序里的第 11 行,a 的初始值为 5。在第 12 行执行 defer 语句的时候,由于 a 等于 5,因此延迟函数 printA 的实参也等于 5。接着我们在第 13 行将 a 的值修改为 10。下一行会打印出 a 的值。该程序输出:

value of a before deferred function call 10  
value of a in deferred function 5

从上面的输出,我们可以看出,在调用了 defer 语句后,虽然我们将 a 修改为 10,但调用延迟函数 printA(a)后,仍然打印的是 5。

 

defer 栈

当一个函数内多次调用 defer 时,Go 会把 defer 调用放入到一个栈中,随后按照后进先出(Last In First Out, LIFO)的顺序执行。

我们下面编写一个小程序,使用 defer 栈,将一个字符串逆序打印。

package main
import (
"fmt"
) func main() {
name := "Naveen"
fmt.Printf("Orignal String: %s\n", string(name))
fmt.Printf("Reversed String: ")
for _, v := range []rune(name) {
defer fmt.Printf("%c", v)
}}
Orignal String: Naveen
Reversed String: neevaN

  

defer 的实际应用

  • file对象打开后的自动关闭
func CopyFile(dstName, srcName string) (written int64, err error) {
src, err := os.Open(srcName)
if err != nil {
return
}
defer src.Close() dst, err := os.Create(dstName)
if err != nil {
return
}
defer dst.Close() // other codes
return io.Copy(dst, src)
}

 在打开输入文件输出文件后,不管后面的代码流程如何影响,这两个文件能够被自动关闭。 

  • mutex对象锁住后的自动释放
func foo(...) {
mu.Lock()
defer mu.Unlock() // code logic
}

确保mu锁能够在函数foo退出之后自动释放。

  • WaitGroup的退出
package main
import (
"fmt"
"sync"
) type rect struct {
length int
width int
} func (r rect) area(wg *sync.WaitGroup) {
defer wg.Done()
if r.length < 0 {
fmt.Printf("rect %v's length should be greater than zero\n", r)
return
}
if r.width < 0 {
fmt.Printf("rect %v's width should be greater than zero\n", r)
return
}
area := r.length * r.width
fmt.Printf("rect %v's area %d\n", r, area)
} func main() {
var wg sync.WaitGroup
r1 := rect{-67, 89}
r2 := rect{5, -67}
r3 := rect{8, 9}
rects := []rect{r1, r2, r3}
for _, v := range rects {
wg.Add(1)
go v.area(&wg)
}
wg.Wait()
fmt.Println("All go routines finished executing")
}

  

 

Go defer使用的更多相关文章

  1. 浅谈Angular的 $q, defer, promise

    浅谈Angular的 $q, defer, promise 时间 2016-01-13 00:28:00  博客园-原创精华区 原文  http://www.cnblogs.com/big-snow/ ...

  2. javascript的defer和async的区别。

    我们常用的script标签,有两个和性能.js文件下载执行相关的属性:defer和async defer的含义[摘自https://developer.mozilla.org/En/HTML/Elem ...

  3. script标签中defer和async属性的区别

    这篇文章来源于JS高级程序设计第三版中关于script标签的介绍,结合查阅的资料写下的学习笔记. 向html页面中插入javascript代码的主要方法就是通过script标签.其中包括两种形式,第一 ...

  4. twitter.common.concurrent deadline and defer

    此defer非golang中的defer https://tour.golang.org/flowcontrol/12 from twitter.common.concurrent import Ti ...

  5. script async 和script defer的区别

    浏览器对js文件的操作主要有两部分:下载和执行: js文件下载在有些浏览器中是并行的,在有些浏览器中是串行的,如:IE8.firefox3.chrome2都是串行下载的: 执行在所有浏览器中默认是阻塞 ...

  6. angular中的$q.defer()服务异步处理

    jquery和angular都有defer服务,我暂以angular为例谈谈我的理解,最后并附上jquery的阮一峰总结的defer. 以我目前项目的部分代码为例说明为什么要用deferred. fu ...

  7. Go语言异常处理defer\panic\recover

    Go语言追求简洁优雅,所以,Go语言不支持传统的 try…catch…finally 这种异常,因为Go语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得混乱.因为开发者很容易滥用异常, ...

  8. 浅谈JavaScript中的defer,async

    引言 开始重读<<JavaScript高级程序设计>>一书,看到关于JavaScript中关于defer.async的部分.网上查询了点资料,觉得蛮好的.现在总结下. defe ...

  9. 【Go入门教程3】流程(if、goto、for、switch)和函数(多个返回值、变参、传值与传指针、defer、函数作为值/类型、Panic和Recover、main函数和init函数、import)

    这小节我们要介绍Go里面的流程控制以及函数操作. 流程控制 流程控制在编程语言中是最伟大的发明了,因为有了它,你可以通过很简单的流程描述来表达很复杂的逻辑.Go中流程控制分三大类:条件判断,循环控制和 ...

  10. go:defer

    defer:延迟. 假设有调用函数A.被调用函数B,其关系如下: func A(){//调用函数 ... defer B()//被调用函数 ... return//B将延迟到return前执行 } * ...

随机推荐

  1. 2019 中国.NET 开发者峰会正式启动

    2014年微软组织并成立.NET基金会,微软在成为主要的开源参与者的道路上又前进了一步.2014年以来已经有众多知名公司加入.NET基金会,Google,微软,AWS三大云厂商已经齐聚.NET基金会, ...

  2. IOS上传到App Store出现证书未安装问题

    今天在提交自己的APP到苹果商店去审核的时候,编译成功后.upload过程中,提示 XXX Select the certificates you wish to include in this pr ...

  3. 02-25 scikit-learn库之决策树

    目录 scikit-learn库之决策树 一.DecisionTreeClassifier 1.1 使用场景 1.2 代码 1.3 参数详解 1.4 属性 1.5 方法 二.DecisionTreeR ...

  4. 机器学习:eclipse中调用weka的Classifier分类器代码Demo

    weka中实现了很多机器学习算法,不管实验室研究或者公司研发,都会或多或少的要使用weka,我的理解是weka是在本地的SparkML,SparkML是分布式的大数据处理机器学习算法,数据量不是很大的 ...

  5. phpstorm格式设置不同导致的Git代码无法正常比较

    多人开发代码,使用Git作为管理工具,遇到一个问题是 : IDE的格式设置不一样导致的整个文件无法正常的比较. window 和 linux 以及 mac 不同平台的换行符是导致这一个问题比较常见的原 ...

  6. SVN工具常用功能总结

    使用SVN作为版本管理工具,可以使用VisualSVN Server+TortoiseSVN搭建SVN版本控制系统,组长安装VisualSVN Server,组员安装TortoiseSVN. Tort ...

  7. 【RabbitMQ 实战指南】一 RabbitMQ入门

    1.消息中间件 1.1.什么是消息中间件 消息中间件(Message Queue Middleware,简称 MQ)是指利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通道来进行分布式系 ...

  8. Mybatis源码阅读 之 玩转Executor

    承接上篇博客, 本文探究MyBatis中的Executor, 如下图: 是Executor体系图 本片博客的目的就是探究如上图中从顶级接口Executor中拓展出来的各个子执行器的功能,以及进一步了解 ...

  9. 你必须知道的容器监控 (2) cAdvisor

    本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章.上一篇我们了解了docker自带的监控子命令以及开源监控工具Weave Scop ...

  10. Zookeeper - 什么是Zookeeper,以及zookeeper的安装(1)

    Zookeeper 什么是Zookeeper? 官网传送门 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的 ...