关于延迟和恢复,以捕获运行时错误。
版本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
为什么它看起来不一样? 谢谢,如果有人能给我详细的信息。
答案 0 :(得分:4)
在版本1中,您的恐慌发生在主goroutine中,因为必须在生成goroutine之前解析[] string {} [2]。
函数的所有参数必须在调度之前解析,而goroutines也没有区别。
goroutine的工作方式与其他任何函数调用基本相同,只是在为调用设置堆栈之后,它在单独的上下文(线程)中执行。
在你的第二个例子中,你正在调用一个没有args的函数,然后在那个函数中你正在惊慌失措。由于在goroutine中没有调用recover(),因此您将看到默认的恐慌处理程序。
defer / recover()只能捕获同一个goroutine中的恐慌。
如果你将延迟/恢复添加到b的顶部,你将能够捕获它并做任何事情(即:像你在#1中那样打印)