前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >golang之panic

golang之panic

作者头像
孤烟
发布2024-02-12 09:06:58
1390
发布2024-02-12 09:06:58
举报
文章被收录于专栏:golang开发笔记

在go语言中,panic是一种用于处理不可恢复错误和异常情况的机制。大多数情况下,我们用panic来快速解决正常运行中出现的异常情况,或者我们没有准备好优雅地处理的错误。

源码版本:go1.21.4

panic源码

runtime/runtime2.go

代码语言:javascript
复制
type _panic struct {
    argp      unsafe.Pointer // pointer to arguments of deferred call run during panic; cannot move - known to liblink 指针指向panic期间运行的延迟调用的参数; 
    arg       any            // argument to panic //参数
    link      *_panic        // link to earlier panic 链接下一个 panic 结构体
    pc        uintptr        // where to return to in runtime if this panic is bypassed 如果绕过此panic,则在运行时返回到何处
    sp        unsafe.Pointer // where to return to in runtime if this panic is bypassed
    recovered bool           // whether this panic is over   panic是否已经结束?
    aborted   bool           // the panic was aborted panic停止了
    goexit    bool
}

触发panic条件

1、用panic函数主动触发

代码语言:javascript
复制
package main

import "fmt"

func main(){
panic("异常")
fmt.Println("end")
}

输出:

代码语言:javascript
复制
panic: 异常

2、操作初始化map,slice等

代码语言:javascript
复制
package main
func main(){
    //示例1
    //var d map[string]string
    //d["a"]="a"
    //示例2
    //var c []string
    //c[1]="aa"
    //示例3
    var h chan int
    close(h)
}

捕获panic信息

通过defer和recover捕获
代码语言:javascript
复制
package main

import "fmt"

func main(){
    defer func() {
        if err := recover(); err != nil {
            fmt.Println(err)
        }
    }()
    panic("被捕获错误信息")
    fmt.Println("hello")
}
多个panic情况

示例1

代码语言:javascript
复制
package main

import "fmt"

func main(){

    defer func() {
        if err := recover(); err != nil {
            fmt.Println(err)
        }
    }()
    panic("被捕获错误信息1")
    panic("被捕获错误信息2")

    fmt.Println("hello")
}

输出:被捕获错误信息1

因为执行第一个panic就结束程序,不会执行后面程序,所以不会只执行第二个panic 示例2

代码语言:javascript
复制
package main

import "fmt"

func main(){

    defer func() {
        if err := recover(); err != nil {
            fmt.Println(err)
        }
    }()
    defer panic("被捕获错误信息1")
    panic("被捕获错误信息2")
    fmt.Println("hello")
}

输出:被捕获错误信息1

这个和上面一样也不会执行第二个panic 示例3

代码语言:javascript
复制
package main

import "fmt"

func main(){
    defer panic("被捕获错误信息1")
    defer func() {
        if err := recover(); err != nil {
            fmt.Println(err)
        }
    }()
    panic("被捕获错误信息2")
    fmt.Println("hello")
}

输出:

代码语言:javascript
复制
被捕获错误信息2
panic: 被捕获错误信息1

先进入defer的 panic,会被执行 示例4

代码语言:javascript
复制
package main

import "fmt"

func main(){
    defer func() {
        if err := recover(); err != nil {
            fmt.Println(err)
        }
    }()
    a:=test()
    fmt.Println(a)
    panic("被捕获错误信息1")
    fmt.Println("hello")
}

func test() (a int)  {
    a=0
    panic("被捕获错误信息2")
    return 
}

输出:被捕获错误信息2 示例5

代码语言:javascript
复制
package main

import "fmt"

func main(){
    defer func() {
        if err := recover(); err != nil {
            fmt.Println(err)
        }
    }()
    go func() {
        panic("被捕获错误信息1")
    }()
}

没有捕捉到panic,说明不同的goroutine,不共享defer 示例6

代码语言:javascript
复制
package main
func main(){
    defer panic("被捕获错误信息1")
    defer panic("被捕获错误信息2")
    defer panic("被捕获错误信息3")
}

输出:

代码语言:javascript
复制
panic: 被捕获错误信息3
    panic: 被捕获错误信息2
    panic: 被捕获错误信息1

示例7

代码语言:javascript
复制
package main

import "fmt"

func main(){

    defer func() {
        if err := recover(); err != nil {
            fmt.Println(err)
        }
    }()
    defer panic("被捕获错误信息1")
    defer panic("被捕获错误信息2")
    defer panic("被捕获错误信息3")

}

输出:被捕获错误信息1 recover只捕获1其他的没有捕获,退出了程序

总结

1、defer、 recover、panic 三者之间顺序 recover放入defer,捕捉panic结束程序之前输出的信息。 2、defer 和recover必须一起才能捕捉panic,如果单独recover,放在panic之前,没有相应错误信息,捕捉不到,放在panic之后,则panic发出结束程序后,不会执行recover。 3、多个panic放入defer会都输出。 4、不同的goroutine,不能捕捉对方的panic信息,不共享defer中的队列。 5、recover只捕捉之后紧邻的panic信息。 6、recover除了捕捉panic信息外,还接管panic退出程序。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-02-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • panic源码
  • 触发panic条件
  • 捕获panic信息
    • 通过defer和recover捕获
      • 多个panic情况
      • 总结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档