再读Golang中的异常处理
一起重温Golang中的异常处理啊?
- 1.Golang语言中没有其他语言中的
try...catch...
语句来捕获异常和异常恢复 - 2.在Golang中我们通常会使用
panic
关键字来抛出异常,在defer
中使用recover
来捕获异常进行具体逻辑处理 - 3.Golang中我们通常会在函数或方法中返回
error
结构对象来判断是否有异常出现
注意事项
- 1.利用
recover
和panic
指令,defer
必须放在panic之前定义(panic会终止其后要执行的代码
). - 2.
recover
只有在defer
调用的函数中才有效,否则recover
无法捕获到panic
. - 3.
recover
处理异常后,业务逻辑会跑到defer
之后的处理片段中 - 4.多个
defer
会形成defer栈
- 5.panic会等到整个
goroutine
退出才会报告错误
常规使用
panic
以及recover
参数类型为空接口(可存储任何类型对象)interface{}
/*
func panic(v interface{})
func recover() interface{}
执行顺序:panic()->带recover的defer
输出结果:
oh my god!panic.
解释:
defer中的recover成功捕获到了panic的异常
*/package main
import ("fmt"
)
func main() {defer func() {if err := recover(); err != nil {fmt.Println(err)}}()panic("oh my god!panic.")
}
- 延迟调用中引发的错误,可被后续延迟调用捕获(
仅最后一个错误被捕获
)
/*
执行顺序:panic()->带panic的defer匿名函数->带recover()的defer匿名函数
输出结果:
catch the panic
解释:
defer中的recover仅能捕获最后一个错误
package main
import ("fmt"
)
func main() {defer func() {if err := recover();err != nil {fmt.Println("catch the panic")}}()defer func() {panic("oh my god! panic.")}()panic("something panic!")}
- 捕获函数
recover()
只有在defer
调用内直接调用才会终止,否则返回nil
/*
代码执行顺序:panic->在匿名函数中嵌套recover的defer函数->带fmt的defer->带recover的defer->在匿名函数中调用recover的defer
输出结果:
defer inner
<nil>
defer recover panic error
解释: 多个defer之间形成defer栈,最底部的defer优先执行;第三个defer打印了recover()的零值`nil`,仅有第一个defer成功捕获了最底部的panic("panic error")
*/
package main
import "fmt"
func main() {defer func() {fmt.Println("defer recover",recover())}()defer recover()defer fmt.Println(recover())defer func() {func(){fmt.Println("defer inner")recover()}()}()panic("panic error")
}
- 将代码块放置在匿名函数中可实现在函数逻辑中进行异常恢复,而不影响主函数
/*
代码执行顺序:匿名函数中的panic语句->匿名函数中i自加运算->匿名函数中的fmt->匿名函数中的defer->主函数中的fmt
输出结果:
i is: 2
解释:panic会终止其之后的执行,因此优先执行匿名函数中的panic之后便被defer中的recover捕获,将i赋值为2,其后匿名函数退出开始继续执行主函数中的fmt.Println语句
*/
package main
import "fmt"
func main() {test()
}
func test() {var i intfunc() {defer func(){if err := recover();err != nil {i = 2}}()panic("something panic!")i = 8fmt.Println("no panic, i is:",i)}()fmt.Println("i is:",i)
}
- goroutine中的recover
注意:
如果一个没有recover
的goroutine
发生了panic,那么整个进程都会挂掉
/*
sync.WaitGroup用来等待一组goroutine的结束,Add方法用来设置等待的goroutine数量,Done方法表示一个goroutine运行结束,使用Wait方法将全部的goroutine阻塞住,直到全部goroutine执行完毕代码执行顺序:goroutine中的逻辑->wg.Wait()->fmt.Println
输出结果:
panic recover assignment to entry in nil map
donw
解释:
在goroutine中我们声明了一个info的map[string]string类型,我们都知道在map,slice,channel都是引用类型,需要使用make函数进行初始化操作之后进行赋值。而这里直接使用info["name"] = "BGBiao"进行赋值导致panic,fmt.Println函数就会被终止执行,从而执行带recover的defer,之后执行带wg.Done()的defer并退出goroutine执行主程序逻辑
*/
package main
import ("fmt""sync"
)
func main() {var wg sync.WaitGroupwg.Add(4)go func() {defer wg.Done()defer func() {if err := recover();err != nil {fmt.Println("panic recover",err)}}()var info map[string]stringinfo["name"] = "BGBiao"fmt.Println(info)}()wg.Wait()fmt.Println("done")
}
欢迎关注我的公众号: BGBiao,一起进步~
再读Golang中的异常处理相关推荐
- golang中container/list包中的坑
转载地址:golang中container/list包中的坑 - Go语言中文网 - Golang中文社区 golang中list包用法可以参看golang中container/list包用法_che ...
- golang中并发sync和channel
golang中并发sync和channel chenbaoke · 2014-12-08 13:00:01 · 19151 次点击 · 预计阅读时间 5 分钟 · 不到1分钟之前 开始浏览 这是一个创 ...
- php协程和goroutine,golang中四种方式实现子goroutine与主协程的同步
如何实现子goroutine与主线程的同步 第一种方式:time.sleep(),这种方式很太死板,就不演示了. 第二种方式:使用channel机制,每个goroutine传一个channel进去然后 ...
- golang中http协议实现
golang中http协议实现 写了一个爬虫,发现出现了socket泄露的情况.百度了一下发现是缺少了Response.Body.Close(),所以导致连接 没有被正常的关闭.也没有被gc回收.下面 ...
- 记一次golang中sync.Map并发创建、读取的问题
记一次golang中sync.Map并发创建.读取的问题 cunfate https://www.jianshu.com/p/f472e79909bc 背景: 我们有一个用go做的项目,其中用到了z ...
- golang中json.Number妙用
golang中json.Number妙用 最近跟某斯调试一个API接口,接口返回数据是json格式 ,按文档描述是一个整型数据,于是定义如下 type Data struct {Api int `js ...
- Java笔记整理六(File类,递归,字节流IO,字符流IO,流中的异常处理,属性集Properties,缓冲流,转换流,序列化,打印流)
1.File类 java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建.查找和删除等操作. 文件和目录路径名的抽象表示 java把文件和文件夹封装位为一个File类,我们可 ...
- golang 中 channel 的详细使用、使用注意事项及死锁分析
什么是 channel 管道 它是一个数据管道,可以往里面写数据,从里面读数据. channel 是 goroutine 之间数据通信桥梁,而且是线程安全的. channel 遵循先进先出原则. 写入 ...
- golang中的atomic,以及CAS操作
CAS无锁算法 要实现无锁(lock-free)的非阻塞算法有多种实现方法,其中CAS(比较与交换,Compare and swap)是一种有名的无锁算法.CAS是CPU指令,在大多数处理器架构,包括 ...
最新文章
- 中如何构造有参和无惨_CAD制图初学入门:CAD机械软件中如何构造孔?
- 线程中应该注意的问题
- springboot 自动配置
- distinct和group by不能一起用_内裤用热水洗更好吗?能不能和袜子一起洗?了解后炎症或能少困扰...
- LOJ-10096(强连通+bfs)
- 轻松Ghost XP系统!
- app和外部应用的关联及应用举例
- 毕业的那天,程序员师兄竟然让我去做这一行
- mysqldump全量恢复_mysql全量备份和快速恢复的方法整理
- Python datatime date
- multisim安装后无法连接数据库_Kepserver连接Mysql教程(一)MySQL5.5数据库安装
- (Trie树)leetcode208: Implement Trie,79:Word Search,DFS与BFS(python实现),212:Word Search2...
- 诺基亚java软件下载_诺基亚手机安装JAVA软件程序
- eclipse 语言包在线更新地址
- 【Python游戏】Python各大游戏合集:超级玛丽、天天酷跑、我的世界、魔塔、雷霆战机 | 附带源码
- excel工作簿合并怎么处理?
- [leetcode]剑指offer(C++版题解)
- CANFiber是什么?
- 客户关系管理项目——客户管理模块设计
- 测度论--长度是怎样炼成的[zz]