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代码执行完成后,才继续渲染页面. ...
随机推荐
- Win32之进程创建过程
0x01. 什么是进程? 进程提供程序所需要的资源,如:数据.代码等等 进程扮演的角色仅仅是为当前程序提供资源,或者代码,这就是进程所提供的,当时程序运行的状态和进程没有关系,进程可以看做空间的概念 ...
- 项目开发中的pro、pre、test、dev环境及SpringBoot多环境配置
一.介绍: pro:生产环境,面向外部用户的环境,连接上互联网即可访问的正式环境. pre:灰度环境,外部用户可以访问,但是服务器配置相对低,其它和生产一样. test:测试环境,外部用户无法访问,专 ...
- 云计算之路-出海记:蹭一张 aws 船票
出海记开篇之后,在 aws 上搭建博客园海外站的出海计划今天开始迈出第一步 -- 注册一个 aws 海外区域账号. aws 现在针对新注册用户提供12个月免费套餐(正在园子里推广并提供了专属注册通道) ...
- 如何k个一组反转链表
之前的文章「递归反转链表的一部分」讲了如何递归地反转一部分链表,有读者就问如何迭代地反转链表,这篇文章解决的问题也需要反转链表的函数,我们不妨就用迭代方式来解决. 本文要解决「K 个一组反转链表」,不 ...
- Spark集群和任务执行
[前言:承接<Spark通识>篇] Spark集群组件 Spark是典型的Master/Slave架构,集群主要包括以下4个组件: Driver:Spark框架中的驱动器,运行用户编写Ap ...
- 使用Haproxy代理rabbitmq集群,用keepalive保证haproxy高可用
原文地址:https://www.jianshu.com/p/440b8e1d5339 使用Haproxy代理rabbitmq集群 上一篇文章教了rabbitmq集群搭建.但是这样搭建出来的集群是3个 ...
- vscode实现远程linux服务器上Python开发
最近需要训练一个生成对抗网络模型,然后开发接口,不得不在一台有显卡的远程linux服务器上进行,所以,趁着这个机会研究了下怎么使用vscode来进行远程开发. 1 配置免密登录¶ (1)在 ...
- 【Kata Daily 190924】Difference of Volumes of Cuboids(长方体的体积差)
题目: In this simple exercise, you will create a program that will take two lists of integers, a and b ...
- 10 XSRF和XSS
10 XSRF和XSS CSRF(Cross-site request forgery)跨站请求伪造 XSS(Cross Site Scripting)跨站脚本攻击 CSRF重点在请求,XSS重点在脚 ...
- 6 MVVM进阶
1. 背景 MVVM是一种常用的设计模式,它的最主要功能是将数据与代码隔离,实现viewmodel的可测试.架构图如下: 2. 命令-Command 2.1 WPF 路由命令 WPF提供一种内置的命令 ...