• Golang入门笔记(14)—— 错误处理


            来一个除以0的异常,代码如下:

    1. package main
    2. import "fmt"
    3. func main() {
    4. fmt.Println("before")
    5. divNum()
    6. fmt.Println("after")
    7. }
    8. func divNum() {
    9. num1 := 10
    10. num2 := 0
    11. result := num1 / num2
    12. fmt.Println(result)
    13. }

            console 异常:

    1. before
    2. panic: runtime error: integer divide by zero
    3. goroutine 1 [running]:
    4. main.divNum()
    5. C:/Users/Lenovo/IdeaProjects/go-helloworld/class02/demo06/main.go:15 +0x11
    6. main.main()
    7. C:/Users/Lenovo/IdeaProjects/go-helloworld/class02/demo06/main.go:8 +0x5b
    8. exit status 2

            恐慌: 运行时 整数除以零的恐慌。

            before 输出后,遇到恐慌异常,代码运行时,因为错误恐慌中断,后面的代码 after并没有执行出来。常常我们不想程序的代码流就这么在运行时就中断掉,就需要引入一些技术,错误能被捕获并处理掉。

            在java中有try...catch...finally 来处理异常,在Go中,为了追求代码的优雅,采用的是defer...recover来处理这里的恐慌panic 。

    defer recover 机制处理错误:

                  defer 前面学过了,但是什么是recover函数?

            官方解释及有道翻译

            The recover built-in function allows a program to manage behavior of a panicking goroutine. 内置包的recover函数允许程序管理恐慌goroutine go程序 的行为。
            Executing a call to recover inside a deferred function (but not any function called by it) stops the panicking sequence by restoring normal execution and retrieves the error value passed to the call of panic. 在延迟函数(而不是它调用的任何函数)内部执行恢复调用,通过恢复正常执行来停止恐慌序列,并检索传递给panic调用的错误值。
            If recover is called outside the deferred function it will not stop a panicking sequence.如果在deferred函数外部调用recover,则不会停止恐慌序列。
            In this case, or when the goroutine is not panicking, or if the argument supplied to panic was nil, recover returns nil. Thus the return value from recover reports whether the goroutine is panicking.在这种情况下,或者当goroutine没有panic,或者提供给panic的参数为nil时,recover将返回nil。因此,recover的返回值报告goroutine是否出现异常。
    
    这里,nil是零值,返回nil 则说明 goroutine 有错误。 代码如下:
    
    1. package main
    2. import "fmt"
    3. func main() {
    4. fmt.Println("before")
    5. divNum()
    6. fmt.Println("after")
    7. }
    8. func divNum() {
    9. //利用defer + recover 捕获错误
    10. // 1.defer 后加一个匿名函数调用。
    11. defer func() {
    12. // 2.匿名函数内开一个局部变量,看 recover返回是 nil 还是错误。。
    13. err := recover()
    14. //3.如果recover 返回的不是零,说明goroutine有错误,打印该错误。
    15. if err != nil {
    16. fmt.Println(err)
    17. }
    18. }()
    19. num1 := 10
    20. num2 := 0
    21. result := num1 / num2
    22. fmt.Println(result)
    23. }
    查看 console 输出:
    
    1. before
    2. runtime error: integer divide by zero
    3. after
    Go语言的自定义错误:
            由于 runtime error: integer divide by zero 对我们不是很友好,看下Go语言是如何支持自定义错误的。
           自定义错误,需要调用errors包瞎的New函数进行操作,函数会返回一个error类型。
    
    1. package main
    2. import (
    3. "errors"
    4. "fmt"
    5. )
    6. func main() {
    7. fmt.Println("before")
    8. err := divNum()
    9. if err != nil {
    10. fmt.Println(err)
    11. }
    12. fmt.Println("after")
    13. }
    14. func divNum() (err error) {
    15. num1 := 10
    16. num2 := 0
    17. // 抛出自定义错误。
    18. if num2 == 0 {
    19. err := errors.New("除数不能为0")
    20. return err
    21. } else {
    22. result := num1 / num2
    23. fmt.Println(result)
    24. return nil
    25. }
    26. }
    上面发生错误,程序正常执行了,有时候,我们希望发生错误,程序停止执行。
    

            panic(err) //抛出异常,停止代码流。相当于java 中的new Exception();

    1. package main
    2. import (
    3. "errors"
    4. "fmt"
    5. )
    6. func main() {
    7. fmt.Println("before")
    8. err := divNum()
    9. if err != nil {
    10. fmt.Println(err)
    11. panic(err) //抛出异常,停止代码流。相当于java 中的new Exception();
    12. }
    13. fmt.Println("after")
    14. }
    15. func divNum() (err error) {
    16. num1 := 10
    17. num2 := 0
    18. // 抛出自定义错误。
    19. if num2 == 0 {
    20. err := errors.New("除数不能为0")
    21. return err
    22. } else {
    23. result := num1 / num2
    24. fmt.Println(result)
    25. return nil
    26. }
    27. }
            That's all , next point ...
    

  • 相关阅读:
    Spark 6:Spark SQL DataFrame
    新的 ChatGPT 提示工程技术:程序模拟
    ACM浅聊
    Docker(上)(安装Docker、配置阿里镜像加速、Docker运行流程、Docker常用命令)
    LINUX 下如何检查服务器是虚拟机,还是物理机
    可编程USB转 UART/I2C /SMBusS/SPI/CAN/1 -Wire适配器USB2S结构尺寸及电压设置
    AGI之MFM:《多模态基础模型:从专家到通用助手》翻译与解读之与LLM协同工作的多模态智能体、结论和研究趋势
    训练yolov5时出现RuntimeError: CUDA out of memory
    【第一部分 | HTML】3:表格、列表和表单
    细品spring设计,可扩展性编程Aware接口,Adapter类
  • 原文地址:https://blog.csdn.net/wdw18668109050/article/details/127926098