Exceptions Handling — throw an exception

In Go, traditional exception handling mechanisms (like those found in Java or Python) do not exist. Instead, Go uses a combination of error values and panic/recover for error and exception handling. "Throwing an exception" in Go is typically done using the panic function.

Throwing an Exception using panic

The panic function in Go can be used to stop the normal flow of control and begin unwinding the stack. It's a way to signal that something unexpected has happened and the program cannot continue.

Here's how you can "throw an exception" using panic:

Example: Simple panic

package main

import (
	"fmt"
)

func main() {
	fmt.Println("Starting the program")

	// Trigger a panic
	throwException("Something went wrong!")

	fmt.Println("This will not be printed")
}

func throwException(message string) {
	panic(message)
}

Explanation

  1. Triggering Panic:

    panic(message)
    
    

    The panic function takes an argument of any type, often a string, which describes the error or exceptional condition.

  2. Unwinding the Stack: When panic is called, the program prints the panic message and starts to unwind the stack, executing any deferred functions along the way, and eventually terminating the program if not recovered.

Handling Panics with recover

To handle panics and potentially allow the program to continue running, you can use the recover function inside a deferred function. This allows you to catch the panic, handle it, and prevent the program from crashing.

Example: Handling a Panic

package main

import (
	"fmt"
)

func main() {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("Recovered from panic:", err)
		}
	}()

	fmt.Println("Starting the program")

	// Trigger a panic
	throwException("Something went wrong!")

	fmt.Println("This will not be printed")
}

func throwException(message string) {
	panic(message)
}

Explanation

  1. Deferred Recovery Function:

    defer func() {
        if err := recover(); err != nil {
            fmt.Println("Recovered from panic:", err)
        }
    }()
    
    

    This deferred function calls recover to catch any panic that occurs in the main function. If a panic is caught, it prints the panic message and the program can continue running if desired.

  2. Panic and Recovery: The panic is triggered in throwException and caught by the deferred function in main. This demonstrates how you can "throw" and "catch" exceptions in Go using panic and recover.

Practical Use Case: Error Handling in a Web Server

In a web server context, you might use panic and recover to handle unexpected errors gracefully without crashing the server:

package main

import (
	"fmt"
	"net/http"
)

func main() {
	http.HandleFunc("/", safeHandler)
	http.ListenAndServe(":8080", nil)
}

func safeHandler(w http.ResponseWriter, r *http.Request) {
	defer func() {
		if err := recover(); err != nil {
			http.Error(w, fmt.Sprintf("Internal Server Error: %v", err), http.StatusInternalServerError)
		}
	}()

	// Simulate an unexpected error
	throwException("A critical error occurred")

	fmt.Fprintln(w, "This will not be printed if panic occurs")
}

func throwException(message string) {
	panic(message)
}