我认为一个等效的问题是-是否所有运行时错误都可能致命,恐慌?因为任何恐慌都应该可以恢复。我不是在谈论从诸如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")
}
Run Code Online (Sandbox Code Playgroud)
输出:
运行时错误:索引超出范围
恢复,主程序结束
是否有一些示例,其中运行时错误将使程序崩溃而没有可恢复的恐慌?
是否有一些示例,其中运行时错误将使程序崩溃而没有可恢复的恐慌?
例如,内存不足(OOM)错误不可恢复。
src/runtime/panic.go:Run Code Online (Sandbox Code Playgroud)// fatalpanic implements an unrecoverable panic. It is like fatalthrow, except // that if msgs != nil, fatalpanic also prints panic messages and decrements // runningPanicDefers once main is blocked from exiting. func fatalpanic(msgs *_panic) { // ... } // fatalthrow implements an unrecoverable runtime throw. It freezes the // system, prints stack traces starting from its caller, and terminates the // process. func fatalthrow() { // ... }
首先更改您的errorHandler()原因,因为如果没有紧急情况,r将会发生nil,因此类型断言将失败:
func errorHandler() {
if r := recover(); r != nil {
fmt.Println(r)
}
}
Run Code Online (Sandbox Code Playgroud)
现在,这里是一些带有代码的示例,这些代码会产生无法恢复的运行时错误:
func foo() {
defer errorHandler()
_ = make([]int64, 1<<40) // You have to change the size on 32-bit systems
}
Run Code Online (Sandbox Code Playgroud)
有关详细信息,请参见如何从并发映射写入中恢复?,例如,请参见能否将map [string] string编组到json会返回错误?
func foo() {
defer errorHandler()
m := map[string]int{}
go func() {
for {
m["x"] = 1
}
}()
for {
_ = m["x"]
}
}
Run Code Online (Sandbox Code Playgroud)
有关详细信息,请参阅Go是否具有等效的“无限调用堆栈”?
func foo() {
defer errorHandler()
var f func(a [1000]int64)
f = func(a [1000]int64) {
f(a)
}
f([1000]int64{})
}
Run Code Online (Sandbox Code Playgroud)
nil函数作为goroutine 启动func foo() {
defer errorHandler()
var f func()
go f()
}
Run Code Online (Sandbox Code Playgroud)
标题说明了一切。这是阻止当前goroutine的简单代码,但是,如果您启动了其他goroutine,则显然不会遇到崩溃。在此处查看其他示例:永远进入项目的主要goroutine睡眠状态吗?
func foo() {
defer errorHandler()
select {}
}
Run Code Online (Sandbox Code Playgroud)
如果您的goroutine被IO操作阻塞,则可能会启动新线程来执行其他goroutine。最大线程数显然有一个限制,如果达到最大线程数,您的应用将崩溃。