mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-16 10:42:27 +08:00
feat: add try-catch-finally implementation
This commit is contained in:
100
xerror/trycatch.go
Normal file
100
xerror/trycatch.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package xerror
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// TryCatch is a struct to handle try-catch-finally block.
|
||||
// This implementation is merely a simulation of Java-style try-catch and does not align with Go's error-handling philosophy. It is recommended to use it with caution.
|
||||
type TryCatch struct {
|
||||
ctx context.Context
|
||||
tryFunc func(ctx context.Context) error
|
||||
catchFunc func(ctx context.Context, err error)
|
||||
finallyFunc func(ctx context.Context)
|
||||
}
|
||||
|
||||
// NewTryCatch creates a new TryCatch instance.
|
||||
func NewTryCatch(ctx context.Context) *TryCatch {
|
||||
return &TryCatch{
|
||||
ctx: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
// Try sets the try function.
|
||||
func (tc *TryCatch) Try(tryFunc func(ctx context.Context) error) *TryCatch {
|
||||
tc.tryFunc = tryFunc
|
||||
return tc
|
||||
}
|
||||
|
||||
// Catch sets the catch function.
|
||||
func (tc *TryCatch) Catch(catchFunc func(ctx context.Context, err error)) *TryCatch {
|
||||
tc.catchFunc = catchFunc
|
||||
return tc
|
||||
}
|
||||
|
||||
// Finally sets the finally function.
|
||||
func (tc *TryCatch) Finally(finallyFunc func(ctx context.Context)) *TryCatch {
|
||||
tc.finallyFunc = finallyFunc
|
||||
return tc
|
||||
}
|
||||
|
||||
// Do executes the try-catch-finally block.
|
||||
func (tc *TryCatch) Do() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if tc.catchFunc != nil {
|
||||
err := fmt.Errorf("panic: %v", r)
|
||||
tc.catchFunc(tc.ctx, WrapCatchError(err, "Recovered from panic"))
|
||||
}
|
||||
}
|
||||
|
||||
if tc.finallyFunc != nil {
|
||||
tc.finallyFunc(tc.ctx)
|
||||
}
|
||||
}()
|
||||
|
||||
if tc.ctx.Err() != nil {
|
||||
if tc.catchFunc != nil {
|
||||
tc.catchFunc(tc.ctx, WrapCatchError(tc.ctx.Err(), "Context cancelled or timed out"))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if tc.tryFunc != nil {
|
||||
if err := tc.tryFunc(tc.ctx); err != nil {
|
||||
if tc.catchFunc != nil {
|
||||
tc.catchFunc(tc.ctx, WrapCatchError(err, "Error in try block"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CatchError is an error type to handle try-catch-finally block.
|
||||
type CatchError struct {
|
||||
Msg string
|
||||
File string
|
||||
Line int
|
||||
Cause error
|
||||
}
|
||||
|
||||
// Error returns the error message.
|
||||
func (e *CatchError) Error() string {
|
||||
return fmt.Sprintf("%s at %s:%d - Cause: %v", e.Msg, e.File, e.Line, e.Cause)
|
||||
}
|
||||
|
||||
// WrapCatchError wraps an error with message, file, and line.
|
||||
func WrapCatchError(err error, msg string) *CatchError {
|
||||
_, file, line, ok := runtime.Caller(2)
|
||||
if !ok {
|
||||
file = "unknown"
|
||||
line = 0
|
||||
}
|
||||
return &CatchError{
|
||||
Msg: msg,
|
||||
File: file,
|
||||
Line: line,
|
||||
Cause: err,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user