【问题标题】:difference between in recover when run goroutine in new func or not在新函数中运行goroutine时恢复之间的区别
【发布时间】:2016-07-03 06:29:34
【问题描述】:

这是关于延迟和恢复,以捕获运行时错误。

版本 1:

func a() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println(r)
        }
    }()
    b()
}

func b() {
    go fmt.Println([]string{}[2])
}

func main() {
    a()
    time.Sleep(1 * time.Second)
    fmt.Println("end")
}

第 2 版(仅更改了 func b()):

func b() {
    go func() {
        fmt.Println([]string{}[2])
    }()
}

区别 运行版本 1:

> go run /tmp/version1.go 
runtime error: index out of range
end

和版本 2:

> go run /tmp/t.go 
panic: runtime error: index out of range

goroutine 5 [running]:
main.b.func1()
    /tmp/t.go:19 +0x109
created by main.b
    /tmp/t.go:20 +0x2b

goroutine 1 [sleep]:
time.Sleep(0x3b9aca00)
    /usr/local/go/src/runtime/time.go:59 +0xf9
main.main()
    /tmp/t.go:25 +0x29
exit status 2

为什么看起来不一样? 如果有人可以给我详细信息,谢谢。

【问题讨论】:

    标签: go deferred goroutine recover


    【解决方案1】:

    在版本 1 中,您的恐慌发生在主 goroutine 中,因为在生成 goroutine 之前必须解决 []string{}[2]。

    函数的所有参数都必须在它被分派之前解析,goroutines 也不例外。

    goroutine 的工作原理与任何其他函数调用基本相同,只是在为调用设置堆栈后,它会在单独的上下文(线程)中执行。

    在您的第二个示例中,您正在调用一个没有参数的函数,然后在该函数中您感到恐慌。由于 goroutine 中没有调用 recover(),因此您看到的是默认的恐慌处理程序。

    defer/recover() 只能在同一个 goroutine 中捕获恐慌。

    如果您在 b 的顶部添加延迟/恢复,您将能够捕获它并执行任何操作(即:println 它就像您在 #1 中所做的那样)

    【讨论】:

      猜你喜欢
      • 2011-01-31
      • 1970-01-01
      • 2013-02-14
      • 2017-01-22
      • 1970-01-01
      • 2012-07-14
      • 2021-08-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多