6.1.错误

Go语言中使用builtin包下error接口作为错误类型

Go语言中错误都作为方法/函数的返回值

自定义错误类型

  1. //Learn_Go/main.go
  2. package main
  3.  
  4. import (
  5. "errors"
  6. "fmt"
  7. )
  8.  
  9. func demo(i,k int) (r int, e error) {
  10. if k == 0 {
  11. e = errors.New("除数不能为0")
  12. return
  13. }
  14. r = i/k
  15. return
  16. }
  17.  
  18. func main() {
  19. //result,error := demo(6,3)
  20. result,e := demo(6,0)
  21. if e != nil{
  22. fmt.Println("执行错误,错误信息为:",e) //执行错误,错误信息为: 除数不能为0
  23. return
  24. }
  25. fmt.Println("执行成功,结果:",result) //执行成功,结果: 2
  26. }

6.2.defer

Go语言中defer可以完成延迟功能,当前函数执行完成后执行defer功能

defer最常用的就是关闭连接(数据库,文件等),可以打开连接后紧跟defer进行关闭

(1)Go语言中defer无论写到哪里都是最后执行,不用非要把关闭代码写在最后

  1. //Learn_Go/main.go
  2. package main
  3.  
  4. import "fmt"
  5.  
  6. func main() {
  7. fmt.Println("打开连接")
  8. //defer fmt.Println("关闭连接")
  9. defer func() {
  10. fmt.Println("关闭连接") //defer执行
  11. }()
  12. fmt.Println("进行操作")
  13. }
  14.  
  15. //结果
  16. 打开连接
  17. 进行操作
  18. 关闭连接

(2)多个defer

多重defer采用栈结构执行,先产生后执行

在很多代码结构中都可能出现产生多个对象,而程序希望这些对象倒叙关闭,多个defer正好可以解决这个问题

  1. //Learn_Go/main.go
  2. package main
  3.  
  4. import "fmt"
  5.  
  6. func main() {
  7. fmt.Println("打开连接A")
  8. defer fmt.Println("关闭连接A")
  9. fmt.Println("打开连接B")
  10. defer fmt.Println("关闭连接B")
  11. fmt.Println("打开连接C")
  12. defer fmt.Println("关闭连接C")
  13. fmt.Println("进行操作")
  14. }
  15.  
  16. //结果
  17. 打开连接A
  18. 打开连接B
  19. 打开连接C
  20. 进行操作
  21. 关闭连接C
  22. 关闭连接B
  23. 关闭连接A

(3)defer和return结合

defer与return同时存在时,要把return理解成两条执行结合,一个指令是给返回值

赋值,另一个指令返回跳出函数

defer和return时整体执行顺序

  • 先给返回值赋值
  • 执行defer
  • 返回跳出函数

(4)没有定义返回值接收变量,执行defer时返回值已经赋值

  1. //Learn_Go/main.go
  2. package main
  3.  
  4. import "fmt"
  5.  
  6. func demo() int {
  7. i := 1
  8. defer func() {
  9. i = i + 2
  10. }()
  11. return i
  12. }
  13.  
  14. func main() {
  15. fmt.Println(demo()) //1
  16. }

(5)声明接收返回值变量,执行defer时修改了返回值内容

  1. //Learn_Go/main.go
  2. package main
  3.  
  4. import "fmt"
  5.  
  6. func demo() (z int) {
  7. i := 1
  8. defer func() {
  9. z = i + 2
  10. }()
  11. return
  12. }
  13.  
  14. func main() {
  15. fmt.Println(demo()) //3
  16. }

6.3.panic

panic是build中函数,当执行到panic后,终止剩余代码执行,并打印错误栈信息。

  1. //Learn_Go/main.go
  2. package main
  3.  
  4. import "fmt"
  5.  
  6. func main() {
  7. fmt.Println("111")
  8. panic("错误信息")
  9. fmt.Println("222")
  10. }
  11.  
  12. //结果
  13. 111
  14. panic: 错误信息
  15.  
  16. goroutine 1 [running]:
  17. main.main()
  18. C:/Users/86158/Desktop/Learn_Go/main.go:8 +0x82

panic不是立即停止程序,defer还是执行的

  1. //Learn_Go/main.go
  2. package main
  3.  
  4. import "fmt"
  5.  
  6. func main() {
  7. defer fmt.Println("执行defer的内容")
  8. fmt.Println("111")
  9. panic("错误信息")
  10. fmt.Println("222")
  11. }
  12.  
  13. //结果
  14. 111
  15. 执行defer的内容
  16. panic: 错误信息
  17.  
  18. goroutine 1 [running]:
  19. main.main()
  20. C:/Users/86158/Desktop/Learn_Go/main.go:9 +0xdc

6.4.recover

 recover()表示回复程序的panic(),让程序正常执行

rcover()是和panic一样都是builtin中函数,可以接受panic的信息,恢复程序的正常执行

recover()一般在defer内部,如果没有panic信息,返回nil;如果有panic,recover会把panic状态取消

  1. //Learn_Go/main.go
  2. package main
  3.  
  4. import "fmt"
  5.  
  6. func main() {
  7. defer func() {
  8. if error := recover();error != nil{
  9. fmt.Println("panic为:", error)
  10. }
  11. }()
  12. fmt.Println("111")
  13. panic("出现了错误信息")
  14. fmt.Println("222")
  15. }
  16.  
  17. //结果
  18. 111
  19. panic为: 出现了错误信息

函数调用过程中panic和recover()

  • recover()只能恢复当前函数级或当前函数调用函数中的panic(),恢复后调用当前级别函数结束,但是调用此函数的函数可以继续执行
  • panic会一直向上传递,如果没有recover()则表示程序终止,但是碰见了recover(),recover()所在级别函数表示没有panic,panic就不会向上传递
  1. //Learn_Go/main.go
  2. package main
  3.  
  4. import "fmt"
  5.  
  6. func demo1() {
  7. fmt.Println("demo1上半部分")
  8. demo2()
  9. fmt.Println("demo1下半部分")
  10. }
  11.  
  12. func demo2() {
  13. fmt.Println("demo2上半部分")
  14. demo3()
  15. fmt.Println("demo2下半部分")
  16. }
  17.  
  18. func demo3() {
  19. fmt.Println("demo3上半部分")
  20. panic("demo3中出现panic")
  21. fmt.Println("demo3下半部分")
  22. }
  23.  
  24. func main() {
  25. fmt.Println("程序开始")
  26. demo1()
  27. fmt.Println("程序结束")
  28. }
  29.  
  30. //结果
  31. 程序开始
  32. demo1上半部分
  33. demo2上半部分
  34. demo3上半部分
  35. panic: demo3中出现panic

 demo3添加recover() 

  1. //Learn_Go/main.go
  2. package main
  3.  
  4. import "fmt"
  5.  
  6. func demo1() {
  7. fmt.Println("demo1上半部分")
  8. demo2()
  9. fmt.Println("demo1下半部分")
  10. }
  11.  
  12. func demo2() {
  13. fmt.Println("demo2上半部分")
  14. demo3()
  15. fmt.Println("demo2下半部分")
  16. }
  17.  
  18. func demo3() {
  19. defer func() {
  20. recover()
  21. }()
  22. fmt.Println("demo3上半部分")
  23. panic("demo3中出现panic")
  24. fmt.Println("demo3下半部分")
  25. }
  26.  
  27. func main() {
  28. fmt.Println("程序开始")
  29. demo1()
  30. fmt.Println("程序结束")
  31. }
  32.  
  33. //结果
  34. 程序开始
  35. demo1上半部分
  36. demo2上半部分
  37. demo3上半部分
  38. demo2下半部分
  39. demo1下半部分
  40. 程序结束

 demo2添加recover()

  1. //Learn_Go/main.go
  2. package main
  3.  
  4. import "fmt"
  5.  
  6. func demo1() {
  7. fmt.Println("demo1上半部分")
  8. demo2()
  9. fmt.Println("demo1下半部分")
  10. }
  11.  
  12. func demo2() {
  13. defer func() {
  14. recover()
  15. }()
  16. fmt.Println("demo2上半部分")
  17. demo3()
  18. fmt.Println("demo2下半部分")
  19. }
  20.  
  21. func demo3() {
  22. fmt.Println("demo3上半部分")
  23. panic("demo3中出现panic")
  24. fmt.Println("demo3下半部分")
  25. }
  26.  
  27. func main() {
  28. fmt.Println("程序开始")
  29. demo1()
  30. fmt.Println("程序结束")
  31. }
  32.  
  33. //结果
  34. 程序开始
  35. demo1上半部分
  36. demo2上半部分
  37. demo3上半部分
  38. demo1下半部分
  39. 程序结束

  

6.Go-错误,defer,panic和recover的更多相关文章

  1. GOLANG错误处理最佳方案errors wrap, Defer, Panic, and Recover

    Simple error handling primitives:        https://github.com/pkg/errors Defer, Panic, and Recover:    ...

  2. 15 Defer, Panic, and Recover

    Defer, Panic, and Recover 4 August 2010 Go has the usual mechanisms for control flow: if, for, switc ...

  3. Golang 入门系列(十四)defer, panic和recover用法

    以前讲过golang 的基本语法.但是,只是讲了一些基础的语法,感兴趣的可以看看以前的文章,https://www.cnblogs.com/zhangweizhong/category/1275863 ...

  4. go语言defer panic recover用法总结

    defer defer是go提供的一种资源处理的方式.defer的用法遵循3个原则 在defer表达式被运算的同时,defer函数的参数也会被运算.如下defer的表达式println运算的同时,其入 ...

  5. panic和recover的使用规则

    转自个人博客 chinazt.cc 在上一节中,我们介绍了defer的使用. 这一节中,我们温习一下panic和recover的使用规则. 在golang当中不存在tye ... catch 异常处理 ...

  6. Golang错误处理函数defer、panic、recover、errors.New介绍

    在默认情况下,当发生错误(panic)后,程序就会终止运行 如果发生错误后,可以捕获错误,并通知管理人员(邮件或者短信),程序还可以继续运行,这当然无可厚非 errors.New("错误信息 ...

  7. Go语言异常处理defer\panic\recover

    Go语言追求简洁优雅,所以,Go语言不支持传统的 try…catch…finally 这种异常,因为Go语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得混乱.因为开发者很容易滥用异常, ...

  8. 【Go入门教程3】流程(if、goto、for、switch)和函数(多个返回值、变参、传值与传指针、defer、函数作为值/类型、Panic和Recover、main函数和init函数、import)

    这小节我们要介绍Go里面的流程控制以及函数操作. 流程控制 流程控制在编程语言中是最伟大的发明了,因为有了它,你可以通过很简单的流程描述来表达很复杂的逻辑.Go中流程控制分三大类:条件判断,循环控制和 ...

  9. go语言中使用defer、panic、recover处理异常

    go语言中的异常处理,没有try...catch等,而是使用defer.panic.recover来处理异常. 1.首先,panic 是用来表示非常严重的不可恢复的错误的.在Go语言中这是一个内置函数 ...

随机推荐

  1. Python之Flask框架项目Demo入门

    Python+Flask框架项目Demo入门 本例子用到了 Flask+蓝图+Flask-Login+SQLAlchemy+WTForms+PyMySQL相关架构 Flask Web框架介绍 Flas ...

  2. 小米笔记本pro 黑苹果系统无法进入系统,频繁重启故障解决记录

    问题1:频繁重启,然后clover丢失 表现情况:开机没有选择macos 或windos的界面 解决办法:进入windows使用工具easyefi,直接添加一个clover start boot,选择 ...

  3. mysql 8.0 group by 不对的问题

    select version(),@@sql_mode;SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));

  4. 升级GCC

    1. wget http://ftp.gnu.org/gnu/gcc/gcc-4.9.4/gcc-4.9.4.tar.gz 2. tar -zxvf gcc-4.9.4.tar.gz 3. cd gc ...

  5. SAP MM Purchase Order History Category

    SAP MM Purchase Order History Category 1) ,These are different categories of PO history which is con ...

  6. maven 学习---转换基于Maven的Web应用程序支持Eclipse IDE

    在上一节教程中,使用Maven创建了一个Web应用程序.这里有一个指南,告诉你如何转换Web应用程序到Eclipse IDE支持的形式. 注意,通过WTP工具Eclipse IDE支持Web应用程序, ...

  7. ROW_NUMBER()实现分页

    1. 在数据表基础上面添加一个自增的一列记录行数(虚拟的实际数据库不存在,不会影响数据库结构)的列当然也顺便起一个别名(我这里起了一个rowNum) 2.由于rowNum是一个虚拟的.若直接使用会报' ...

  8. Android系统源码目录

    Android系统源码目录 我们要先了解Android系统源码目录,为后期源码学习打下基础.关于源码的阅读,你可以访问http://androidxref.com/来阅读系统源码.当然,最好是将源码下 ...

  9. leetcode - 括号字符串是否有效

    括号字符串是否有效 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效. 有效字符串需满足: 左括号必须用相同类型的右括号闭合. 左括号必须以正确的顺序闭合. ...

  10. Django restframework 序列化之 ModelSerializer 小记

    首先介绍一下相关概念 序列化器(Serializer) 1. 自定义型:  继承rest_framework.serializers.Serializer 2. 模型类型:  继承rest_frame ...