go特性-defer
1:后定义的defer先执行(可以理解为栈的方式)
// 222
// 111
func Test1(t *testing.T) {
defer fmt.Println("111")
defer fmt.Println("222")
}
2:defer定义的函数的参数,在定义的时候已经被赋值了
// defer 函数定义的时候,参数已经被赋值了(参数被捕捉了)
// 输出:
// 第二个defer: 2
// 第一个defer: 1
func Test2(t *testing.T) {
a := 1
// 注意这里,a作为defer函数的参数。defer函数定义的时候,就把a的值确定了
defer fmt.Println("第一个defer: ", a)
defer func() {
fmt.Println("第二个defer: ", a)
}()
a+=1
}
3:defer函数可以修改具名返回值,但不会修改匿名返回值
/////////////////////////////////////////////////////////
// defer 函数可以修改具名返回值,但是不会修改匿名返回值
// 输出
// fHasName: 2
// fNoName: 1
func fHasName() (val int) {
val = 1
defer func() {
// 因为val是个具名返回值,所以这里对val的操作,会影响到返回值
val += 1
}()
return val
}
func fNoName() int {
val := 1
defer func() {
// 这里的操作则不会影响返回值
val += 1
}()
return val
}
4:遇到panic的时候,当前协程调用栈已定义的defer将被执行,如果当前协程没有任何一个defer函数内执行了recover,那么执行完所有的defer之后,将会触发panic退出进程
/* 输出
has: 333
err: haha
has: 222
has: 111
*/
func TestHasRecover(t *testing.T) {
defer fmt.Println("has: 111")
defer fmt.Println("has: 222")
defer func() {
if err := recover(); err != nil {
fmt.Println("err:", err)
}
}()
defer fmt.Println("has: 333")
panic("haha")
defer fmt.Println("has: 444")
}
/* 输出
has: 333
has: 222
has: 111
panic: haha [recovered]
panic: haha
goroutine 19 [running]:
testing.tRunner.func1.1(0x95df20, 0x9b2110)
C:/Go/src/testing/testing.go:1076 +0x310
testing.tRunner.func1(0xc000140480)
C:/Go/src/testing/testing.go:1079 +0x43a
*/
func TestNoRecover(t *testing.T) {
defer fmt.Println("has: 111")
defer fmt.Println("has: 222")
defer fmt.Println("has: 333")
panic("haha")
defer fmt.Println("has: 444")
}
最后来一道总结题,如下代码会输出什么?
import "testing"
import "fmt"
func sum(tip string, a int, b int) int {
sum := a + b
fmt.Printf("tip=%s a=%d b=%d sum=%d\n", tip, a, b, sum)
return sum
}
func deferSum() {
a := 1
b := 2
defer sum("1tip", a, sum("2tip", a, b))
a = 3
defer func(b int) {
sum("3tip", a, sum("4tip", a, b))
}(a)
b = 4
defer func() {
sum("5tip", a, sum("6tip", a, b))
}()
}
func TestDeferSum(t *testing.T) {
deferSum()
}
正确答案如下:
tip=6tip a=3 b=4 sum=7
tip=5tip a=3 b=7 sum=10
tip=4tip a=3 b=3 sum=6
tip=3tip a=3 b=6 sum=9
tip=1tip a=1 b=3 sum=4
go特性-defer的更多相关文章
- golang学习 ---defer语句
golang语言defer特性详解 defer语句是go语言提供的一种用于注册延迟调用的机制,它可以让函数在当前函数执行完毕后执行,是go语言中一种很有用的特性.由于它使用起来简单又方便,所以深得go ...
- Python也可以拥有延迟函数
延迟函数defer 我们知道在Golang中有一个关键字defer,用它来声明在函数调用前,会让函数*延迟**到外部函数退出时再执行,注意,这里的退出含义:函数return返回或者函数panic退出 ...
- 浏览器环境下JavaScript脚本加载与执行探析之defer与async特性
defer和async特性相信是很多JavaScript开发者"熟悉而又不熟悉"的两个特性,从字面上来看,二者的功能很好理解,分别是"延迟脚本"和"异 ...
- Go defer 特性和使用场景
golang 的 defer 语句用于延迟调用.defer 会在当前函数返回之前执行 defer 注册的函数.比如 defer func_defer() 这样语句会让你注册一个函数变量到 defer ...
- JS魔法堂:ES6新特性——GeneratorFunction介绍
一.前言 第一次看koajs的示例时,发现该语句 function *(next){...............} ,这是啥啊?于是搜索一下,原来这是就是ES6的新特性Generator ...
- 【Go入门教程3】流程(if、goto、for、switch)和函数(多个返回值、变参、传值与传指针、defer、函数作为值/类型、Panic和Recover、main函数和init函数、import)
这小节我们要介绍Go里面的流程控制以及函数操作. 流程控制 流程控制在编程语言中是最伟大的发明了,因为有了它,你可以通过很简单的流程描述来表达很复杂的逻辑.Go中流程控制分三大类:条件判断,循环控制和 ...
- iOS - Swift Swift 语言新特性
1.Swift 2.0 带来哪些新变化 常规变化: 1.OS X 10.11.iOS 9 和 watchOS 2 SDK 采纳了一些 Objective-C 的特性用来提高 Swift 的编程体验, ...
- HTML5 <script>元素async,defer异步加载
原文地址:HTML5′s async Script Attribute原文日期: 2010年09月22日翻译日期: 2013年08月22日 (译者注: 异步加载,可以理解为无阻塞并发处理.) (译者再 ...
- javascript笔记——js的阻塞特性[转载]
JS具有阻塞特性,当浏览器在执行js代码时,不能同时做其它事情,即<script>每次出现都会让页面等待脚本的解析和执行(不论JS是内嵌的还是外链的),JS代码执行完成后,才继续渲染页面. ...
随机推荐
- 【DeepLearning】LeNet-5
手写字体识别模型LeNet5诞生于1994年,是最早的卷积神经网络之一.原文地址为Gradient-Based Learning Applied to Document Recognition,感谢网 ...
- PLC模拟量采集模块在工控领域的应用
在工业现场中,往往需要对温度.电流.电压等模拟量进行控制采集,这可以使用PLC对这些数据进行采集,但是如今生产各种PLC模拟量采集模块的厂家非常多,不同类型的PLC都是有自己专属的模拟量采集模块的,不 ...
- Spark集群和任务执行
[前言:承接<Spark通识>篇] Spark集群组件 Spark是典型的Master/Slave架构,集群主要包括以下4个组件: Driver:Spark框架中的驱动器,运行用户编写Ap ...
- odbc。INI配置
[ODBC Data Sources] ST = OSCAR ODBC DRIVER [ST] Driver = /opt/ShenTong/odbc/lib/liboscarodbcw.so Ser ...
- redis 在windows 下的安装和使用
1.下载试用 首先下载https://github.com/dmajkic/redis/downloads,我下载的是2.4.5的版本,是个压缩包解压后里面有两个文件夹一个是32bit一个是64位的, ...
- 内网渗透 day11-免杀框架
免杀框架 目录 1. venom框架 2. shelltel框架 3. backdoor factory(BDP) 1. venom框架 cd venom进入venom文件夹中./venom.sh进入 ...
- vbox复制虚拟机之后修改ethx号使得可以上网
vbox复制虚拟机之后修改ethx号使得可以上网: (1).改硬件mac编号[此项需要重启] vi /etc/udev/rules.d/70-persistent-net.rules 然后删掉上面一行 ...
- 2012年游戏软件开发独立本科段01B0815自考科目
01B0815自考科目 课程代码[学分] 课程名称 03708[02] 中国近现代史纲要 03709[04] 马克主义基本原理概论 03684[10] 综合英语(四) 01042[05] 应用数学 0 ...
- epoll内核源码详解(转 作者:赛罗·奥特曼 来源:牛客网)
发现自己发的一篇面经后,很多小伙伴向我索要epoll的内核源码实现,那我就在牛客网发下这源码还有自己总结的流程. 另外 网上很多博客说epoll使用了共享内存,这个是完全错误的 ,可以阅读源码,会发现 ...
- 利用matlibplot绘制雷达图
之前在一些数据分析案例中看到用 Go 语言绘制的雷达图,非常的漂亮,就想着用matlibplot.pyplot也照着画一个,遗憾的是matlibplot.pyplot模块中没有直接绘制雷达图的函数,不 ...