包中 init 函数引发的 panic 只能在 init 函数中捕获,在 main 中无法被捕获的示例没看明白

ameyume
博客专家认证
2019-07-23 08:17:22
包中 init 函数引发的 panic 只能在 init 函数中捕获,在 main 中无法被捕获,原因是 init
数先于 main 执行,函数并不能捕获内部新启动的 goroutine 所抛出的 panic 。
示例代码如下,没看懂输出结果:
package main

import (
"fmt"
"time"
)

func do() {
//这里并不能获取da函数中的panic
defer func() {
if err := recover();err != nil{
fmt.Println(err)
}
}()
go da()
go db()
time.Sleep(3*time.Second)
}
func da(){
panic("panic da")
for i := 0; i<10; i++{
fmt.Println(i)
}
}
func db(){
for i := 0; i<10; i++{
fmt.Println(i)
}
}
func main() {
fmt.Println(do)
fmt.Println(da)
fmt.Println(db)
}

运行结果输出如下,输出的为什么是地址呢?
0x402534
0x40261a
0x402680
...全文
437 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
ameyume 2019-07-25
  • 打赏
  • 举报
回复
多谢指导,捕获住异常后就可以正常执行完main函数了。 修改后的一种情况:
package main

import (
    "fmt"
    "time"
)

func do() int {
    //这里并不能获取da函数中的panic
    defer func() {
        if err := recover();err != nil{
            fmt.Println("do recover err: ", err)
        } else {
            fmt.Println("do err is nil");
        }
    } ()

    fmt.Println("do invoke da return ", da())

    fmt.Println("do before sleep")
    time.Sleep(1*time.Second)
    fmt.Println("do after sleep")
    return 1
}

func da() int{
    fmt.Println("---------- start da ----------")

    defer func() {
        if err := recover();err != nil{
            fmt.Println("da recover err: ", err)
        } else {
            fmt.Println("da err is nil");
        }
    } ()
    
    panic("panic da")
    for i := 0; i<10; i++{
        fmt.Println("da i = ", i)
    }
    
    fmt.Println("---------- end da ----------")
    return 1
}

func main() {
    fmt.Println("============= Start =============");

    fmt.Println("do return ", do())
    fmt.Println("da return ", da())

     fmt.Println("============= End =============");
}
输出: ============= Start ============= ---------- start da ---------- da recover err: panic da do invoke da return 0 do before sleep do after sleep do err is nil do return 1 ---------- start da ---------- da recover err: panic da da return 0 ============= End =============
qybao 2019-07-25
  • 打赏
  • 举报
回复
或者你不用注释掉do里的go da(),把捕获异常的处理写在da里,你再执行看看你就清楚了,程序不会挂掉,正常输出一切
qybao 2019-07-25
  • 打赏
  • 举报
回复
你这个结果不就是说明问题了吗,go da()的panic在do里没法捕获,运行到da的panic程序就挂了,异常被抛出
你把do里的go da()注释,然后把捕获异常的处理加在main里,运行一遍,然后再把main的捕获异常的代码注释掉再执行一遍,你就清楚了
qybao 2019-07-24
  • 打赏
  • 举报
回复
这能通过编译?没试过,感觉这应该打印的是函数的入口地址
函数并不能捕获内部新启动的 goroutine 所抛出的 panic 的意思是
func do() {
//这里并不能获取da函数中的panic
defer func() {
if err := recover();err != nil{
fmt.Println(err)
}
}()
go da() //da的panic在do里没法捕捉,也就是do的defer func里的recover()是nil
go db() //同上,
//如果要捕捉goroutine的panic,应该是
//go func () {
// defer func() {
// if e := recover(); e != nil {
// xxx
// }
// da()
//}
time.Sleep(3*time.Second)
}

init是package加载的时候(import)被调用的,所以早于main方法,所以main捕获不到的(main还没开始就panic了)
ameyume 2019-07-24
  • 打赏
  • 举报
回复
原来输出的的确是地址,修改后如下:
package main

import (
    "fmt"
    //"errors"
    //"os"
    "time"
)

func do() int {
    //这里并不能获取da函数中的panic
    defer func() {
        if err := recover();err != nil{
            fmt.Println(err)
        } else {
            fmt.Println("err is nil");
        }
        //da()
    } ()
    go da()
    //go db()
    
    
    fmt.Println("do before sleep")
    time.Sleep(3*time.Second)
    fmt.Println("do after sleep")
    return 1
}
func da() int{
    panic("panic da")
    for i := 0; i<10; i++{
        fmt.Println("da i = ", i)
    }
    return 1
}
func db(){
    for i := 0; i<10; i++{
        fmt.Println("db i = ", i)
    }
}

func main() {
    fmt.Println("do return ", do())
    fmt.Println("da return ", da())
    fmt.Println(db)
    
     println("func main end")
    //os.Exit(1)
}

输出结果如下: ame@ame:~/go/helloworld$ ./hello panic: panic da goroutine 3 [running]: main.da /home/ame/go/helloworld/hello.go:30 created by main.do /home/ame/go/helloworld/hello.go:20 goroutine 1 [runnable]: main.do /home/ame/go/helloworld/hello.go:24 main.main /home/ame/go/helloworld/hello.go:43

2,190

社区成员

发帖
与我相关
我的任务
社区描述
go语言学习与交流版
社区管理员
  • go语言社区
  • Freeman Z
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧