A Go utility package that provides try-catch-finally exception handling mechanism for Go, inspired by traditional exception handling in languages like Java, Python, and JavaScript.
- Try-Catch-Finally pattern implementation
- Multiple exception types with predefined error types
- Custom exception types support
- Panic recovery - automatically catches and handles Go panics
- Stack trace information for debugging
- Nested exception handling support
- Fluent API for chaining operations
go get github.com/mew-sh/except
package main
import (
"fmt"
"github.com/mew-sh/except"
)
func main() {
e := except.New()
e.Try(func() {
data := getValue() // your function that might fail
if data != 100 {
e.Throw(e.AssertionError("Expected value is not the same as 100"))
}
}).
Catch(e.In(e.AssertionErrorType, e.ValueErrorType), func(excep *except.Exception) {
fmt.Println("Message:", excep.Message)
fmt.Println("Exception Type:", excep.Type)
fmt.Println("Here is the Stack Trace:", excep.StackTrace)
}).
Catch(nil, func(excep *except.Exception) {
fmt.Println("I'll be executed as fallback:", excep.Message)
}).
Finally(func() {
fmt.Println("I have been executing always to clean the world!")
}).
Run()
}
Creates a new exception handler instance.
Executes the provided function and captures any exceptions or panics.
Handles specific exception types. Pass nil
as the first parameter for a catch-all handler.
Executes cleanup code that runs regardless of whether an exception occurred.
Executes the try-catch-finally flow. Must be called at the end of the chain.
Throws an exception.
Creates a list of exception types for matching in catch blocks.
The package provides the following predefined exception types:
AssertionErrorType
- For assertion failuresIndexErrorType
- For index out of bounds errorsRuntimeErrorType
- For runtime errorsValueErrorType
- For invalid valuesNetworkErrorType
- For network-related errorsSyntaxErrorType
- For syntax errorsPermissionErrorType
- For permission-related errorsTimeoutErrorType
- For timeout errorsTypeErrorType
- For type-related errorsConnectionErrorType
- For connection errorsReferenceErrorType
- For reference errorsEOFErrorType
- For end-of-file errorsLookupErrorType
- For lookup/key not found errorsUnknownErrorType
- For unknown errors
Each exception type has a corresponding constructor method:
e := except.New()
// Create exceptions with optional custom messages
assertionErr := e.AssertionError("Custom assertion message")
indexErr := e.IndexError("Index out of bounds")
runtimeErr := e.RuntimeError("Runtime failure")
valueErr := e.ValueError("Invalid value provided")
networkErr := e.NetworkError("Network connection failed")
// ... and so on for all types
You can create custom exception types:
const MyCustomErrorType except.ExceptionType = "MyCustomError"
e := except.New()
e.Try(func() {
e.Throw(e.NewException(MyCustomErrorType, "This is a custom error"))
}).
Catch(e.In(MyCustomErrorType), func(excep *except.Exception) {
fmt.Printf("Caught custom error: %s\n", excep.Message)
}).
Run()
e := except.New()
e.Try(func() {
// Code that might throw an exception
if someCondition {
e.Throw(e.ValueError("Invalid input"))
}
}).
Catch(e.In(e.ValueErrorType), func(excep *except.Exception) {
fmt.Printf("Value error: %s\n", excep.Message)
}).
Run()
e := except.New()
e.Try(func() {
// Code that might throw different types of exceptions
}).
Catch(e.In(e.NetworkErrorType, e.TimeoutErrorType, e.ConnectionErrorType), func(excep *except.Exception) {
fmt.Printf("Network-related error: %s\n", excep.Message)
}).
Catch(e.In(e.ValueErrorType, e.TypeError), func(excep *except.Exception) {
fmt.Printf("Data-related error: %s\n", excep.Message)
}).
Catch(nil, func(excep *except.Exception) {
fmt.Printf("Fallback handler: %s\n", excep.Message)
}).
Run()
The package automatically recovers from Go panics:
e := except.New()
e.Try(func() {
panic("Something went wrong!")
}).
Catch(nil, func(excep *except.Exception) {
fmt.Printf("Caught panic: %s\n", excep.Message)
}).
Run()
e1 := except.New()
e1.Try(func() {
e1.Throw(e1.NetworkError("Primary network failure"))
}).
Catch(e1.In(e1.NetworkErrorType), func(excep1 *except.Exception) {
fmt.Printf("Primary error: %s\n", excep1.Message)
// Handle recovery logic that might also fail
e2 := except.New()
e2.Try(func() {
e2.Throw(e2.TimeoutError("Recovery attempt timed out"))
}).
Catch(e2.In(e2.TimeoutErrorType), func(excep2 *except.Exception) {
fmt.Printf("Recovery error: %s\n", excep2.Message)
}).
Run()
}).
Finally(func() {
fmt.Println("Cleanup completed")
}).
Run()
e := except.New()
e.Try(func() {
// Code that might fail
}).
Catch(nil, func(excep *except.Exception) {
// Handle any exception
}).
Finally(func() {
// This always executes for cleanup
fmt.Println("Cleaning up resources...")
}).
Run()
The Exception
struct contains the following fields:
type Exception struct {
Message string // The error message
Type ExceptionType // The type of exception
StackTrace string // Stack trace information
}
- Always call
Run()
at the end of your exception handling chain - Use specific exception types when possible instead of catch-all handlers
- Leverage the Finally block for cleanup operations
- Create custom exception types for domain-specific errors
- Use descriptive error messages when throwing exceptions
Run the tests to ensure everything works correctly:
go test -v
This project is open source and available under the MIT License.
Contributions are welcome! Please feel free to submit a Pull Request.