• 06、GO异常处理


    1. 错误处理 (error handling)
    如果函数实现过程中,如果出现不能处理的错误,可以返回给调⽤者处理。
    ⽐如我们调⽤标准库函数 os.Open 读取⽂件
    os.Open 2 个返回值,第⼀个是 *File ,第⼆个是 error
    如果调⽤成功, error 的值是 nil => nil 是⼀个空值
    如果调⽤失败,例如⽂件不存在,将返回⼀个⾮空 error 。我们可以通过 error 知道具体的错误信息。
    1. package main
    2. import "fmt"
    3. import "os"
    4. func main() {
    5. fmt.Println("vim-go")
    6. _, err := os.Open("a.txt")
    7. if err != nil {
    8. fmt.Println("出错啦")
    9. fmt.Println(err)
    10. }
    11. }
    1. [root@localhost src]# go run error.go
    2. vim-go
    3. 出错啦
    4. open a.txt: no such file or directory

    可以通过 errors.New 返回⾃定义的错误

    1. package main
    2. import "fmt"
    3. import "os"
    4. import "errors"
    5. func main() {
    6. fmt.Println("vim-go")
    7. _, err := os.Open("a.txt")
    8. if err != nil {
    9. fmt.Println("出错啦")
    10. fmt.Println(err)
    11. }
    12. }
    13. func myprint(name string) error {
    14. if len(name) == 0 {
    15. return errors.New("error: name is null")
    16. }
    17. fmt.Println(name)
    18. return nil
    19. }
    1. [root@localhost src]# go run error.go
    2. vim-go
    3. 出错啦
    4. open a.txt: no such file or directory
    4. defer
    defer有延迟的意思,就是稍后执⾏,先执⾏函数主体内容,defer的内容稍后执⾏
    主体内容执⾏完毕后,defer的内容按照调⽤顺序的 相反顺序 逐个执⾏defer 的执⾏⽅式类似其他语⾔中的 析构函数 即使函数发⽣ 严重错误 也会执⾏
    常⽤于 资源清理、⽂件关闭、解锁以及记录时间 等操作⽀持匿名函数的调⽤通过与匿名函数配合可在return之后 修改 函数计算结果
    如果函数体内某个变量作为defer时匿名函数的参数,则在定义defer时即已经获得了拷⻉,否则则是引⽤某个变量的地址

     示例:使用defer关键字

    1. func main() {
    2. fmt.Println("main_a")
    3. defer fmt.Println("deffer_a")
    4. fmt.Println("main_b")
    5. defer fmt.Println("deffer_b")
    6. fmt.Println("main_c") }
    1. # go run func.go
    2. main_a
    3. main_b
    4. main_c
    5. deffer_b
    6. deffer_a
    5. panic
    panic英⽂意思是恐慌,在这⾥意思是抛出⼀个程序异常,即报告程序运⾏时错误
    当在⼀个函数执⾏过程中调⽤ panic() 函数时,正常的函数执⾏流程将⽴即终⽌,可以理解为 Throw
    之前使⽤ defer 关键字延迟执⾏的语句将正常展开执⾏,并导致逐层向上执⾏ panic 流程
    直⾄所属的 goroutine 中所有正在执⾏的函数被终⽌。
    错误信息将被报告,包括在调⽤ panic() 函数时传⼊的参数,这个过程称为错误处理流程。
    1. package main
    2. import "fmt"
    3. func main(){
    4. defer fmt.Println("deferred main")
    5. sayHi("")
    6. }
    7. func sayHi(name string){
    8. defer fmt.Println("deferred sayHi")
    9. if len(name)<1{
    10. panic("hahaha")
    11. }
    12. fmt.Println("hi", name)
    13. fmt.Println("bla,bla")
    14. }

     输出结果

    1. deferred sayHi
    2. deferred main
    3. panic: hahaha
    4. goroutine 1 [running]:
    5. main.sayHi({0x0?, 0x60?})
    6. /Users/beebol/golearn/c.go:13 +0x149
    7. main.main()
    8. /Users/beebol/golearn/c.go:7 +0x74
    9. exit status 2
    执⾏过程:
    执⾏到 panic("hahaha") 时,程序控制权交给defer
    ⾸先 sayHi ⽅法中的 defer 被执⾏,输出: deferred sayHi
    接着,从 sayHi ⽅法返回到main ⽅法中的 defer 被执⾏,输出: deferred main
    最后,调⽤返回到顶层函数,然后将错误消息和堆栈信息打印出来。

     6. recover

    recover() 函数⽤于终⽌错误处理流程,也就是我们常规说的 catch。
    recover() 应该在⼀个使⽤ defer 关键字的函数中执⾏,以有效截取错误处理流程。
    Panic 可以在任何地⽅引发,但 recover 只有在 defer 调⽤的函数中有效
    如果没有在发⽣异常的 goroutine 中明确调⽤恢复过程(使⽤ recover 关键字),会导致该 goroutine 所属
    的进程打印异常信息后直接退出。

     示例:
     

    1. package main
    2. import "fmt"
    3. func main(){
    4. sayHi("")
    5. fmt.Println("end!!")
    6. }
    7. func sayHi(name string){
    8. arr := []int{1,2,3}
    9. defer recoverSayHi()
    10. if len(name)<1{
    11. fmt.Println(arr[5])
    12. // panic("hahaha")
    13. }
    14. fmt.Println("hi", name)
    15. fmt.Println("bla,bla")
    16. }
    17. func recoverSayHi(){
    18. fmt.Println("you can clean")
    19. if r := recover(); r!=nil{
    20. fmt.Println("recoved from", r)
    21. }
    22. }
    执⾏过程
    调⽤sayHi函数,recoverSayHi() 被延迟执⾏
    sayHi中遇到异常/调⽤panic,触发defer recoverSayHi
    recoverSayHi中的 recover() 捕捉到了这个异常,并停⽌了异常继续向上抛
    它调⽤了 recover(),并接收到 panic 的错误信息。
  • 相关阅读:
    LeetCode每日一题(985. Sum of Even Numbers After Queries)
    Leetcode:125.验证回文串,917仅仅反转字母,387字符串的第一个唯一字符
    python判断是否为回文字符串
    使用Python进行Web开发:从基础到实战
    分析 java.util.LinkedHashMap
    [附源码]Python计算机毕业设计SSM开放性实验室网上预约管理(程序+LW)
    springboot(spring)整合redis(集群)、细节、底层配置讲解
    最新720全景云系统/可生成小程序+带PC端+安装教程/价值800元的720云全景系统源码
    Tomcat实现WebSocket即时通讯 & Java实现WebSocket的两种方式
    微前端架构的理解
  • 原文地址:https://blog.csdn.net/qq_48391148/article/details/126191888