go-defer语句
- Go语言中的defer语句也非常独特。
- defer语句仅能被放置在函数或方法中。
- 它由关键字defer和一个调用表达式组成。
- 调用表达式所表示的既不能是对Go语言内建函数的调用
- 也不能是对Go语言标准库代码包unsafe中的那些函数的调用。
- 实际上,满足上述条件的调用表达式被称为表达式语句。
- func readFile(path string) ([]byte, error) {
- file, err := os.Open(path)
- if err != nil {
- return nil, err
- }
- defer file.Close()
- return ioutil.ReadAll(file)
- }
- 打开指定文件且未发现有错误发生之后,紧跟了一条defer语句。
- 其中携带的表达式语句表示的是对被打开文件的关闭操作。
- 注意,当这条defer语句被执行的时候,其中的这条表达式语句并不会被立即执行。
- 它的确切的执行时机是在其所属的函数(这里是readFile)的执行即将结束的那个时刻。
- 在readFile函数真正结束执行的前一刻,file.Close()才会被执行。
- 这也是defer语句被如此命名的原因。
- 语句defer file.Close()的含义是在打开文件并读取其内容后及时地关闭它。
- 该语句可以保证在readFile函数将结果返回给调用方之前,那个文件或目录一定会被关闭。
- 这实际上是一种非常便捷和有效的保险措施。
- 当一个函数中存在多个defer语句时,它们携带的表达式语句的执行顺序一定是它们的出现顺序的倒序。
- 下面的示例可以很好的证明这一点:
- func deferIt() {
- defer func() {
- fmt.Print()
- }()
- defer func() {
- fmt.Print()
- }()
- defer func() {
- fmt.Print()
- }()
- fmt.Print()
- }
- deferIt函数的执行会使标准输出上打印出4321
- defer携带的表达式语句代表的是对某个函数或方法的调用。这个调用可能会有参数传入。
- 如果代表传入参数的是一个表达式,那么在defer语句被执行的时候该表达式就会被求值了。
- func deferIt3() {
- f := func(i int) int {
- fmt.Printf("%d ",i)
- return i *
- }
- for i := ; i < ; i++ {
- defer fmt.Printf("%d ", f(i))
- }
- }
- 它在被执行之后,标准输出上打印出1 。
- defer携带的表达式语句代表的是对匿名函数的调用,那么我们就一定要非常警惕。请看下面的示例:
- func deferIt4() {
- for i := ; i < ; i++ {
- defer func() {
- fmt.Print(i)
- }()
- }
- }
- deferIt4函数在被执行之后标出输出上会出现5555,而不是4321
- 原因是defer语句携带的表达式语句中的那个匿名函数包含了对外部(确切地说,是该defer语句之外)的变量的使用。
- 注意,等到这个匿名函数要被执行(且会被执行4次)的时候,包含该defer语句的那条for语句已经执行完毕了。
- 此时的变量i的值已经变为了5。因此该匿名函数中的打印函数只会打印出5。
- 正确的用法是:把要使用的外部变量作为参数传入到匿名函数中。
- 修正后如下:
- func deferIt4() {
- for i := ; i < ; i++ {
- defer func(n int) {
- fmt.Print(n)
- }(i)
- }
- }
go-defer语句的更多相关文章
- [Go] defer 语句
Go 还有一些特有的流程控制语句,其中一个就是 defer 语句.该语句用于延迟调用指定的函数,它只能出现在函数的内部,由 defer 关键字以及针对某个函数的调用表达式组成.这里被调用的函数称为 延 ...
- go语言之goto语句和函数和defer语句
1.goto关键字 import "fmt" func main() { for i := 0;i <11;i++{ if i == 2{ //关键字,goto跳转到某个位置 ...
- golang学习 ---defer语句
golang语言defer特性详解 defer语句是go语言提供的一种用于注册延迟调用的机制,它可以让函数在当前函数执行完毕后执行,是go语言中一种很有用的特性.由于它使用起来简单又方便,所以深得go ...
- go语言的defer语句
转: https://www.jianshu.com/p/5b0b36f398a2 ---------------------------------------------------------- ...
- Go语言中defer语句使用小结
defer是Go语言中的延迟执行语句,用来添加函数结束时执行的代码,常用于释放某些已分配的资源.关闭数据库连接.断开socket连接.解锁一个加锁的资源.Go语言机制担保一定会执行defer语句中的代 ...
- 探究 Go 语言 defer 语句的三种机制
Golang 的 1.13 版本 与 1.14 版本对 defer 进行了两次优化,使得 defer 的性能开销在大部分场景下都得到大幅降低,其中到底经历了什么原理? 这是因为这两个版本对 defer ...
- Go语言学习——函数二 defer语句
函数 package main import "fmt" // 函数:一段代码的封装 func f1(){ fmt.Println("Hello 中国!") } ...
- go defer 语句会延迟函数的执行直到上层函数返回。
defer code... 可以理解为 执行完当前defer所在的方法代码后执行defer 中的代码 常用在释放资源 比如 关闭文件 为防止忘记编写关闭代码 可以先写好 defer 各种释放资源 ...
- 【Go入门教程3】流程(if、goto、for、switch)和函数(多个返回值、变参、传值与传指针、defer、函数作为值/类型、Panic和Recover、main函数和init函数、import)
这小节我们要介绍Go里面的流程控制以及函数操作. 流程控制 流程控制在编程语言中是最伟大的发明了,因为有了它,你可以通过很简单的流程描述来表达很复杂的逻辑.Go中流程控制分三大类:条件判断,循环控制和 ...
- go:defer
defer:延迟. 假设有调用函数A.被调用函数B,其关系如下: func A(){//调用函数 ... defer B()//被调用函数 ... return//B将延迟到return前执行 } * ...
随机推荐
- 15 (OC)* UIGesture
前言 本文主要内容如下: 1. UIGestureRecognizer 属性.方法.代理和七个子类详解. 2. 讲讲 UIGestureRecognizer 和 UITouch 事件的关系. 3. 讲 ...
- Android嵌入式开发初学者的几个注意点
一:首先你必须了解ARM平台 Android 移植与驱动核心开发,当然也可以是X86和其他的平台,不过其他平台的Android智能终端开发并不是很多. Android嵌入式智能操作系统是基于Linux ...
- Java匹马行天下之 Java国出了个Java——举国欢庆
Java帝国的崛起 前言: 看庭前花开花落,宠辱不惊, 望天上云卷云舒,去留无意. 闹心的事儿,选择释怀: 纠缠的人儿,试着放下, 生活其实很美. 心若向阳,就无惧悲伤. 愿你明朗坦荡纵情豁达,有得有 ...
- Unity-遇到的问题小总结
1. event trigger后面显示不了对应的方法 原因:我是直接把脚本拖拽进去的,这是没有实例化的,拖拽进去的应该是挂载这个脚本的GameObject就可以了 2.制作prefeb 将场景中的单 ...
- 配置文件my.cnf---配置信息注释大全
在进行MySQL与CM+CHD之间的应用配置时,发现此前对于MySQL的配置含义过于模糊,所以将CM+CHD集群所涉及MySQL方面的配置含义进行抽取并加以注释,方便此后的配置和使用. 一.客户端设置 ...
- elasticsearch应用于产品列表
package com.linkwee.web.service; import java.util.List; import com.linkwee.api.request.cim.ProductPa ...
- Ubuntu 启动zookeeper报错
在启动zk客户端连接server时报错: 2019-03-30 23:06:24,915 [myid:localhost:2181] - INFO [main-SendThread(localhost ...
- 阿里云ESC服务器centos6.9使用及注意事项
阿里云ESC服务器,配置低,但是足够新手尝试操作练习. 使用之前,注意事项: 选择操作系统 设置实例快照 安装终端工具 一,选择操作系统. 可以在购买服务器的时候进行选择系统盘,也可以在购买之后在实例 ...
- 如何让谷歌浏览器支持小于12px的字体
CSS3有个新的属性transform,而我们用到的就是transform:scale() 书写一段代码 <body> <p>我是一个小于12PX的字体</p> & ...
- axios对put操作对Android的支持之坑
### 前段时间我做的一个手机端H5项目,需要发送一个put请求.因为ajax现在用的人有点少了,而且公司里边都是用的axios,所以我也是用的是axios做的请求. ### 再开发的时候测试都没有问 ...