SoFunction
Updated on 2025-03-04

Extremely detailed explanation of panic, recover functions and defer statements in GoLang

1. Panic when running

panic is an exception thrown at runtime. For example, "index of range".

Details of panic:

package main
import "fmt"
func main() {
	oneC := []int{1, 2, 3, 4, 5}
	v5 := oneC[5]
	(v5)
}

$ go run
panic: runtime error: index out of range [5] with length 5

goroutine 1 [running]:
()
    /Users/lifei/Documents/workspace/githubRepositoies/gowp/projects/go-core-example/src/article19/q1/:7 +0x1b
exit status 2
$

The first line of the print message, "panic:" on the right is exactly what panic containsString representation of type values;

"goroutine 1 [running]" means that there is a goroutine with id 1 running when the panic is triggered;

The ID number here is not important. It is a goroutine number given by the GO language runtime system. We cannot obtain or change it in the program.

Next, the following is to indicate which line has an error. "+0x1b" represents the offset of this line of code relative to the entry program count of the function to which it belongs, and is generally of little use.

The last "exit status 2" indicates that my program is running with exit status code 2.

In most operating systems, as long as the exit status code is not 0, it means that the program runs abnormally.

2. The process of panic being triggered to the program termination

A function undoubtedly triggers panic:

  • The initial panic details will be established, and the execution of the function to which this line of code is terminated randomly.
  • Control is immediately transferred to the previous level;
  • Control propagates to the top layer in the reverse direction of the call stack, which is the outermost function we write;
  • Ultimately, control is taken back by the GO language runtime system. The program then crashes and terminates its run;

Panic details will be gradually accumulated and improved during the process of control propagation, and control will be propagated to the top step by step in the reverse direction of the call stack. Therefore, in the code execution information for a certain goroutine, the information at the bottom of the call stack will appear first, then the information at the previous level call, and so on, and finally the information at the top of the call stack.

3. Intentionally trigger a panic and let the panic contain a value

  • A panic can be initiated intentionally using the panic function.
  • When calling a panic function, just pass a certain value as a parameter to the function. Since the only argument to the panic function is of type null interface (that is, interface{}), it can accept any type of value syntactically.
  • However, it is better to pass in an error value of type error, or other values ​​that can be validly serialized. "Efficient serialization" here means that the representation form conversion can be more readable.

Print error message:

  • For various printing functions under the fmt package, the Error method of error type value is equivalent to the String method of other types of values, and their only results are of string type;
  • If a value may be recorded in the log, then the String method should be associated with it.

4. Implement protection measures to deal with panic to avoid program crashes

Only by combining the defer statement and the recover function call can a panic that has occurred.

The built-in function recover in GO language is specially used to restore panic. The recover function requires no parameters and returns a value of the empty interface type.

The defer statement is used to delay code execution. Delay until the moment the function where the statement is located is about to end, regardless of the reason for the end of execution.

Limitations: Some calling expressions cannot appear here, including: calling expressions for built-in functions in Go language, and calling expressions for functions in unsafe packages.

package main
import (
	"errors"
	"fmt"
)
func main() {
	("Enter function main")
	// Delay the execution of the func function until the end of main	defer func() {
		("Enter defer function")
		if p := recover(); p != nil {
			("%v\n", p)
		}
		("Exit defer function")
	}()
	// Raise painc	panic(("soming wrong"))
	("Exit function main")
}

5. Multiple defer statements Execution order of multiple defer statements

In the same function, the execution order of the defer function calls is exactly the opposite of the order of occurrence of the defer statements to which they belong (more strictly, the execution order).

When a function is about to end execution, the defer function call written at the bottom will be executed first, followed by the defer function call written at the top and closest to it, and so on, the defer function call on the top will be executed last.

The inside story of the execution of the defer statement:

Each time the defer statement is executed, the Go language will store the defer function and its parameter values ​​it carries into a linked list.

This linked list corresponds to the function to which the defer statement belongs, and it is first-in and later (FILO), equivalent to a stack.

When you need to execute a defer function call in a certain function, Go will first get the corresponding linked list, then take out the defer function and its parameter values ​​from the linked list one by one, and execute the calls one by one.

package main
import "fmt"
func main() {
	defer ("first defer")
	for i := 0; i < 3; i++ {
		defer ("defer in for %d\n", i)
	}
	defer ("last defer")
}

This is the article about this detailed explanation of panic, recover functions and defer statements in GoLang. For more related Go panic recover defer content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!