我认为一个等效的问题是-是否所有运行时错误(可能致命, panic )?因为任何 panic 症都应该是可以恢复的。我不是在说从os.Exit()
或log.Fatal()
或Go运行时中的错误或某人通过电源线跳闸中恢复,而是从其他运行时错误中恢复,这将导致程序崩溃。
这是可以通过紧急/恢复捕获的运行时错误的示例:
package main
import (
"fmt"
)
func errorHandler() {
r := recover()
err := r.(error)
if err == nil {
return
}
fmt.Println(err.Error())
}
func foo() {
defer errorHandler()
smallSlice := []int{1, 0, 1}
smallSlice[10] = 1
}
func main() {
foo()
fmt.Println("recovery, end of main")
}
输出:
是否有一些示例,其中运行时错误将使程序崩溃而又没有可恢复的 panic ?
最佳答案
首先更改您的errorHandler()
,因为如果没有 panic ,则r
将是nil
,因此类型声明将失败:
func errorHandler() {
if r := recover(); r != nil {
fmt.Println(r)
}
}
现在,这里是一些带有代码的示例,这些代码会产生无法恢复的运行时错误:
1.内存不足:
func foo() {
defer errorHandler()
_ = make([]int64, 1<<40) // You have to change the size on 32-bit systems
}
2.并发映射读写
有关详细信息,请参见How to recover from concurrent map writes?,例如,请参见Can marshalling a map[string]string to json return an error?
func foo() {
defer errorHandler()
m := map[string]int{}
go func() {
for {
m["x"] = 1
}
}()
for {
_ = m["x"]
}
}
3.堆栈内存耗尽
有关详细信息,请参见Does Go have an "infinite call stack" equivalent?
func foo() {
defer errorHandler()
var f func(a [1000]int64)
f = func(a [1000]int64) {
f(a)
}
f([1000]int64{})
}
4.尝试将
nil
函数作为goroutine启动func foo() {
defer errorHandler()
var f func()
go f()
}
5.所有goroutine都在 sleep 中-死锁
标题说明了一切。这是阻止当前goroutine的简单代码,但是,如果您启动了其他goroutine,则显然不会遇到崩溃。在此处查看其他示例:Go project's main goroutine sleep forever?
func foo() {
defer errorHandler()
select {}
}
6.线程限制用尽
如果您的goroutine被IO操作阻塞,则可能会启动新线程来执行其他goroutine。最大线程数显然有一个限制,如果达到最大线程数,您的应用程序将崩溃。
关于go - Go中是否可以恢复所有运行时错误?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57486620/