I think an equivalent question is - do all runtime errors, which may be fatal, panic? Because anything that panics should be recoverable. I'm not talking about recovering from things like os.Exit()
, or log.Fatal()
, or bugs in the Go runtime, or someone tripping over the power cord, but from other runtime errors which will lead to the program crashing.
Here's an example of a runtime error that can be caught via panic/recover:
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")
}
output:
runtime error: index out of range
recovery, end of main
Are there any examples where runtime errors will just crash the program without a recoverable panic?
A panic stops the normal execution of a goroutine: When a program panics, it immediately starts to unwind the call stack. This continues until the program crashes and prints a stack trace, or until the built-in recover function is called.
Golang panic We use the panic statement to immediately end the execution of the program. If our program reaches a point where it cannot be recovered due to some major errors, it's best to use panic. The lines of code after the panic statement are not executed. For example, package main import "fmt" func main() { fmt.
What is panic() in Golang? Samia Ishaque. The panic() function in Go Language is similar to exceptions raised at runtime when an error is encountered. panic() is either raised by the program itself when an unexpected error occurs or the programmer throws the exception on purpose for handling particular errors.
Overview. The recover() function in Go Language is used to recover from a goroutine that is in panic, meaning it helps recover from an error that has been raised. The program takes control through recover rather than letting the code crash. recover() is an inbuilt function in Go Language.
First change your errorHandler()
because if there are no panics, r
will be nil
and thus the type assertion would fail:
func errorHandler() {
if r := recover(); r != nil {
fmt.Println(r)
}
}
And now here are some examples with code to produce unrecoverable runtime errors:
func foo() {
defer errorHandler()
_ = make([]int64, 1<<40) // You have to change the size on 32-bit systems
}
For details see How to recover from concurrent map writes?, for example see 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"]
}
}
For details, see 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{})
}
nil
function as a goroutinefunc foo() {
defer errorHandler()
var f func()
go f()
}
Title says it all. Here's a simple code to block the current goroutine, but if you have launched other goroutines, you obviously won't experience the crash. See other examples here: Go project's main goroutine sleep forever?
func foo() {
defer errorHandler()
select {}
}
If your goroutines get blocked by IO operations, new threads may be started to execute your other goroutines. There is obviously a limit to the max thread count, if it is reached, your app will crash.
Are there any examples where runtime errors will just crash the program without a recoverable panic?
For example, Go Out-Of-Memory (OOM) errors are not recoverable.
src/runtime/panic.go
:// 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() { // ... }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With