Contents
Error Handling
Syntax
In Go, errors are represented by the built-in error
type, which is an interface with a single method Error() string
. The error
type is used to indicate an unexpected state or failure in a program. Go functions that may fail typically return an error as their last return value. If an error occurs, it can be checked and handled appropriately. Go’s error handling approach encourages explicit checks and handling, which leads to clear and robust code.
Example:
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf("cannot divide by zero")
}
return a / b, nil
}
func main() {
result, err := divide(4, 0)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Result:", result)
}
Creating Errors
Errors in Go can be created using the errors.New
function from the errors
package or using fmt.Errorf
to format the error message. You can define custom error types by implementing the error
interface, allowing for more descriptive and structured error handling. Custom errors can carry additional context about the failure, which can be useful for debugging and handling specific error cases.
Example:
type CustomError struct {
Code int
Message string
}
func (e *CustomError) Error() string {
return fmt.Sprintf("Error %d: %s", e.Code, e.Message)
}
func doSomething(flag bool) error {
if !flag {
return &CustomError{Code: 404, Message: "Resource not found"}
}
return nil
}
func main() {
err := doSomething(false)
if err != nil {
fmt.Println(err) // Output: Error 404: Resource not found
}
}
Panic and Recover
panic
is a built-in function in Go that stops the normal execution of the current goroutine and begins panicking. When a function panics, it unwinds the stack, executing any deferred functions before the program crashes. Panics are typically used for unrecoverable errors or conditions that should not happen. recover
is another built-in function that regains control of a panicking goroutine. It’s used within deferred functions to handle the panic and prevent the program from crashing, allowing for graceful error handling and recovery.
Example:
func mayPanic() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
fmt.Println("Starting")
panic("something went wrong") // Triggers panic
fmt.Println("This will not be printed")
}
func main() {
mayPanic()
fmt.Println("Program continues")
}
Defer Statement
The defer
statement in Go is used to schedule a function to be executed after the surrounding function completes, regardless of whether it completes normally or due to a panic. Deferred functions are executed in LIFO (Last In, First Out) order. This feature is particularly useful for resource cleanup, such as closing files, unlocking mutexes, or handling any necessary finalization tasks.
Example:
func main() {
fmt.Println("Opening file")
defer fmt.Println("Closing file") // This will execute at the end
fmt.Println("Reading file")
defer fmt.Println("Done reading") // This will execute just before closing
fmt.Println("Processing file")
}