SoFunction
Updated on 2025-03-05

Golang exception control handler error process

Panic and recover use

Go does not support the traditional try…catch…finally exception, because Go designers believe that mixing exceptions with control structures can easily mess up the code. In Go, designers recommend using multi-value returns to return errors. In case of real exceptions (such as the divisor is 0). Only use the Exception introduced in Go: defer, panic, recover.

The usage scenarios of these exceptions can be described in this simple way: a panic exception can be thrown in Go, and then the exception is caught through recover in defer, and then processed normally

Example of usage

package main
import "fmt"
func main(){
    ("c")
     defer func(){ // Defer must be declared first, otherwise the panic exception cannot be caught        ("d")
        if err:=recover();err!=nil{
            (err) // The err here is actually the content passed in by panic, 55        }
        ("e")
    }()
    f() //Start call f    ("f") //The following code will not be executed again after starting here}
func f(){
    ("a")
    panic("Exception information")
    ("b") //The following code will not be executed again after starting here    ("f")
}

Output result:

c
a
d
Exception information
e

Notice

  • Use recover to process panic instructions, recover needs to be defined within the defer anonymous function
  • Defer needs to be declared before panic, otherwise recover cannot capture panic when panic
  • If panic is not recovered, the program will crash directly

subfunction panic main function recover

func TestPanic(t *) {
	defer func() {
		if err := recover(); err != nil {
			println("recovered")
		}
	}()
	subFun()
	subFun()
}
func subFun() {
	println("subFun")
	panic("subFun panic")
}

The output result is as follows, the code after the first sunFun will not be executed

subFun
recovered

child coroutine panic main function recover

func subFun(i int) {
	("subFun,i=", i)
	panic("subFun panic")
}
func TestSubGoPanic(t *) {
	defer func() {
		if err := recover(); err != nil {
			println("recovered2")
		}
	}()
	go subFun(3)
	subFun(4)
	println("finish")
}

result
subFun,i= 4
recovered2
subFun,i= 3
--- PASS: TestSubGoPanic (0.00s)
panic: subFun panic

goroutine 21 [running]:
/base/(0x0?)
    /Users/albert/file/code/go/zh/gotest/base/err/panic_test.go:34 +0x89
created by /base/
    /Users/albert/file/code/go/zh/gotest/base/err/panic_test.go:43 +0x46

Recover will execute, but the program crashes

Summary of use

If panic and recover occur in the same coroutine, then recover is catchable. If panic and recover occur in different coroutines, then recover is not catchable

That is, which coroutine has panic, and which coroutine must have recovery, otherwise the entire program will crash

Some worries about using panic

performance

It is very common to encounter panic when developing using Golang. However, the impact of panic on performance is relatively small, especially in actual use.

First, Golang maintains a panic heap at runtime to store panic objects in the stack. When a program encounters panic, the panic object is added to the panic heap. The size of the panic heap is limited. If there are too many objects in the heap, it may cause the panic heap to overflow, which will affect the performance of the program.

Performance comparison

func BenchmarkSubFunWithError(b *) {
	for i := 0; i < ; i++ {
		go subFunWithError(i)
	}
}
func BenchmarkSubFunWithRecover(b *) {
	for i := 0; i < ; i++ {
		go subFunWithRecover(i)
	}
}
func subFunWithRecover(i int) {
	//("subFun,i=", i)
	defer func() {
		if error := recover(); error != nil {
			//println("subFunWithRecover_recovered")
		}
	}()
	()
	panic("subFun panic")
}
func subFunWithError(i int) error {
	//("subFun,i=", i)
	()
	return ("subFunWithError")
}
BenchmarkSubFunWithError-12               673920              1992 ns/op             489 B/op          3 allocs/op
BenchmarkSubFunWithRecover-12            1000000              1229 ns/op             240 B/op          2 allocs/op

Instead, using panic has better performance?

Safety

Another thing that is more worrying is that panic can easily cause crashes, but as shown above, as long as recovery is done in the main method, each go coroutine uses the encapsulated method with recovery to call it, there will be no problem in fact.

This is the article about the error process of Golang exception control handler. For more related Golang exception control content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!