Golang 中没有内置的类似 (try…catch…finally) 的异常处理手段,但是有其他的替代方案。

文章目录

  • 关键的内置函数和关键字
    • panic
    • defer
      • defer特性
      • defer执行顺序
      • defer语句中的变量
      • defer中的闭包
    • recover
  • 异常处理实现
    • 示例一:获取并打印 panic
    • 示例二:获取 panic 并转换为 error
    • 协程之能处理当前协程的 panic

关键的内置函数和关键字

panic

Golang 的内置函数,当运行到这个函数时,系统会抛出运行时异常,如果没有逻辑兜底,那么系统代码将不再向下继续执行。
如下代码将打印出堆栈信息及代码出错的位置

func panicCreater() {is := 0fmt.Println(10 / is)
}
func main() {fmt.Println("1")fmt.Println("2")is := 0fmt.Println(10 / is)fmt.Println("3")
}
---------------------
1
2
panic: runtime error: integer divide by zerogoroutine 1 [running]:
main.panicCreater()e:/,,,GoLearning/demo44.go:10 +0x11
main.main()e:/,,,GoLearning/demo44.go:41 +0xca
exit status 2

defer

defer特性

  • 关键字 defer 用于注册延时调用
  • 该调用在方法最后执行( retrun 或者抛出 panic 恐慌之前)
  • 多个 defer 函数将按照先进后出的顺序执行
  • defer 语句中的变量在 defer 声明时就已经确认了

defer执行顺序

上面说到 defer 函数将按照先进先出的顺序执行,下面用一段代码进行解释:
其实这就是类似于压栈的操作,先声明的 defer 语句先进入链表,这个链表与该 defer 语句所属的函数是对应的,该链表遵循先入后出的原则。

func main() {defer func() { fmt.Println("1111") }()defer func() { fmt.Println("2222") }()defer func() { fmt.Println("3333") }()defer func() { fmt.Println("4444") }()
}
---------------------------
4444
3333
2222
1111

defer语句中的变量

defer 语句中的变量在 defer 声明时就已经确认了,即如果我们在调用中传递了参数,这个参数会立即被计算
如下代码:
通过打印记录可以看出来,我们 defer 语句里面作为参数的函数被立即执行了。
然后真正的 defer 语句在函数最后被调用,且保持先进后出的原则。

func paramTest(index int) int {fmt.Println(index)return index + 100
}
func main() {defer paramTest(paramTest(1))defer paramTest(paramTest(2))
}
-----------------------
1
2
102
101

defer中的闭包

同时我们要小心闭包带来的影响。
如下:我们发现打印结果全是 5
原因是 defer 语句执行的匿名函数没有接受任何参数,只是直接使用了外部作用域中的变量 i,只有在main方法的最后,当真正执行这个调用的时候,才会去寻找这个 i 的值,此时 i 已经变成了 5

func main() {for i := 0; i < 5; i++ {defer func() { fmt.Println(i) }()}
}
-----------------------
5
5
5
5
5

解决方法就是,将 i 作为匿名函数的参数传入进去。

func main() {for i := 0; i < 5; i++ {defer func(i int) { fmt.Println(i) }(i)}
}
--------------------
4
3
2
1
0

recover

用来控制一个 goroutine 的 panicking 行为,捕获 panic,并恢复系统运行。要注意 recover 只能恢复当前协程的 panic 恐慌。
一般和 defer 配合使用,因为要确保系统能够走到 recover 函数。

异常处理实现

一般来说,我们要尽量的将业务可能出现的报错区分开来,对于业务逻辑上允许的错误,我们使用 error

示例一:获取并打印 panic

defer 语句一般定义在函数的最开始,为确保一定会执行。

func panicCreater() {is := 0fmt.Println(10 / is)
}
func undertake() {if p := recover(); p != nil {fmt.Printf("panic printer: %s\n", p)} else {fmt.Printf("panic printer: %s\n", "none panic")}
}
func main() {defer undertake()//触发抛出异常panicCreater()
}
------------------------
panic printer: runtime error: integer divide by zero

示例二:获取 panic 并转换为 error

func test() (err error) {defer func() {if p := recover(); p != nil {err = fmt.Errorf("panic to error: %s", p)}}()panicCreater()return
}
func main() {err := test()fmt.Println(err)
}
------------------------
panic printer: runtime error: integer divide by zero

协程之能处理当前协程的 panic

当前协程不能获取到其他协程抛出的 panic 恐慌。
如下,系统直接抛出恐慌、退出运行

func main() {defer undertake()for i := 0; i < 10; i++ {go func() {panicCreater()}()}time.Sleep(1000)
}
---------------------------
panic: runtime error: integer divide by zerogoroutine 1 [running]:
main.panicCreater()e:/,,,GoLearning/demo44.go:32 +0x11
main.main()e:/,,,GoLearning/demo44.go:42 +0x2a
exit status 2

对于协程内产生的恐慌,我们需要在当前协程内去处理:

func main() {for i := 0; i < 5; i++ {go func() {defer undertake()panicCreater()}()}time.Sleep(1000)
}
------------------------------
panic printer: runtime error: integer divide by zero
panic printer: runtime error: integer divide by zero
panic printer: runtime error: integer divide by zero
panic printer: runtime error: integer divide by zero
panic printer: runtime error: integer divide by zero

Go学习笔记 -- 异常处理相关推荐

  1. 云计算学习笔记---异常处理---hadoop问题处理ERROR org.apache.hadoop.hdfs.server.datanode.DataNode: java.lang.NullPoin

    云计算学习笔记---异常处理---hadoop问题处理ERROR org.apache.hadoop.hdfs.server.datanode.DataNode: java.lang.NullPoin ...

  2. (JAVA学习笔记) 异常处理

    文章目录 什么是异常 异常分类 异常体系结构 Error Exception Error和Exception的区别: 异常处理机制 代码演示 自定义异常 代码演示 什么是异常 异常指程序运行中出现的不 ...

  3. python基础学习笔记——异常处理

    异常处理流程图 一,异常和错误 part1:程序中难免出现错误,而错误分成两种 1.语法错误(这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正) #语法错误示范一 if #语法 ...

  4. Python学习笔记-异常处理

    异常处理 Python Errors and Exceptions 官方文档 引发异常: 语法: 使用raise 关键字, raise either an exception instance or ...

  5. JAVA学习笔记——异常处理与调试

    目录 错误与异常 异常分类 声明受查异常 抛出异常 创建异常类 异常捕获与处理 基本结构 再次抛出异常与异常链 带资源的 try 语句 使用异常机制的技巧 断言的使用 启用和禁用断言 使用断言完成参数 ...

  6. Java学习笔记 --- 异常处理

    一.基本介绍 异常处理就是当异常发生时,对异常处理的方式 二.异常处理的方式 1.try - catch - finally 程序员在代码中捕获发生的异常,自行处理 处理机制示意: try {代码// ...

  7. Java学习笔记——异常处理

    目录 一.异常 (一)异常的相关概念 (二)异常产生的原因 (三)异常的分类 二.Exception (一)检查性异常 (二)非检查性异常 (三) 异常方法 三.Java处理异常的关键字 (一)捕获异 ...

  8. asp.net学习笔记异常处理001---.framework4.0中asp.net页面ValidateRequest=false 无效的问题

    在做牛腩新闻发布系统的时候,部分同学可能会遇到这样的情况: 从客户端(ContentPlaceHolder1_m_ContentPlaceHolder_ftbContent="<P&g ...

  9. 秒杀项目学习笔记-异常处理

    目的:将校验失败的错误信息在客户端显示出来. 实现:新建一个全局异常拦截器,拦截绑定异常BindException,输出错误信息,并且优化返回信息的过程. GlobleExceptionHandler ...

最新文章

  1. conda环境里安装pydot
  2. 监控MySQL数据库的主从状态的shell脚本
  3. python opencv生成模糊图像
  4. 基于Pytorch再次解读ResNet现代卷积神经网络
  5. 图像解码之一——使用libjpeg解码jpeg图片
  6. OSI模型中的数据链路层和物理层的区分
  7. 【pmcaff】一个PM的十年分享:如果的事
  8. 我需要用的Jupyter Notebook快捷键
  9. c语言是自动四舍五入,请问c语言如何实现四舍五入?
  10. idea git 整合使用
  11. Java事务管理之Spring+Hibernate
  12. 阻止系统自动睡眠的小软件,附C#制作过程
  13. (转)H.264 RTP payload 格式
  14. java返回语句_Java中return的语句
  15. 软件工程技术--第四章 概要设计
  16. cad导入mysql_CAD插入一个数据库
  17. 人的9种2266对联文字的世界纪录(图)
  18. python查看微信撤回消息怎么弄_Python | 查看微信撤回的消息(完整代码)
  19. VSLAM学习记录-求导:李群与李代数
  20. 使用命令行操作Windows防火墙

热门文章

  1. (13.1.1)PMBOK之一:运营,项目、项目集、项目组合、组织战略及其管理
  2. 【BLE】CC2541之Large OAD
  3. 神武4手游等待服务器响应,《神武4》手游快速告别自闭 还能这样玩?
  4. 没有良好数学基础,应该怎样学习人工智能?
  5. iis服务器部署项目,IIS环境下部署项目的详细教程
  6. 浅谈【CSS】渐变背景(background-image)以及基础用法
  7. apache2 不解析php,apache2不解析php怎么办
  8. spring4开发SpringBatch 样例 -配置文件版
  9. python 如何匹配一撇字符_使用Python正则表达式解析斜杠和撇号
  10. html圆形分成六份,在ai里怎么把一个圆平均分成几份