Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Go Panic Recovery and Custom Error Generation

Tech 1

When a Go program encounters a severe execution fault, such as an integer division by zero, the runtime triggers a panic, immediately halting execution and printing a stack trace.

package main

import "fmt"

func ExecuteDivision() {
	numerator := 42
	denominator := 0
	outcome := numerator / denominator
	fmt.Println(outcome)
}

Executing the above function yields a runtime crash:

panic: runtime error: integer divide by zero
goroutine 1 [running]:
main.ExecuteDivision()
	/main.go:8 +0x11
...

Intercepting Panics with defer and recover

To prevent a panic from terminating the entire application, Go provides the recover built-in function. When called within a deferred function, recover stops the panicking sequence, captures the error value passed to panic, and allows the program to resume normal executoin.

package main

import "fmt"

func SafeDivision() {
	defer func() {
		if r := recover(); r != nil {
			fmt.Println("Panic successfully intercepted:")
			fmt.Println("Error detail:", r)
		} else {
			fmt.Println("Execution completed without issues.")
		}
	}()

	numerator := 42
	denominator := 0
	outcome := numerator / denominator
	fmt.Println(outcome)
}

Output:

Panic successfully intercepted:
Error detail: runtime error: integer divide by zero

Returning Safe Defaults After Recovery

If a function needs to return a value even when a panic occurs, named return values can be modified inside the deferred recovery block.

  1. Define the function with named return variables.
  2. Assign a fallback value to the named variable within the recover logic.
package main

import (
	"fmt"
)

func SafeDivisionWithDefault() (result int, err error) {
	defer func() {
		if r := recover(); r != nil {
			fmt.Println("Recovered from panic:", r)
			result = -1
		}
	}()

	numerator := 42
	denominator := 0
	result = numerator / denominator
	return result, nil
}

Calling SafeDivisionWithDefault will return -1 and <nil> instead of crashing.

Defining and Triggering Custom Errors

For business logic violations where standard error handling is preferred, the errors.New function creates custom error messages.

package main

import (
	"errors"
	"fmt"
)

func ValidateAge(age int) (int, error) {
	if age < 0 {
		return 0, errors.New("age cannot be negative")
	}
	return age, nil
}

When a custom error indicates an unrecoverable state that must stop the application immediately, the error can be passed directly to panic.

package main

import (
	"errors"
	"fmt"
)

func ProcessAge(age int) {
	_, err := ValidateAge(age)
	if err != nil {
		fmt.Println("Validation failure:", err)
		panic(err)
	}
	fmt.Println("Age is valid")
}

Invoking ProcessAge(-5) prints the validation failure message and then triggers a panic with the custom error, terminating the program.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.