1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-04 12:52:28 +08:00
Files
lancet/xerror/trycatch.go
2024-11-04 14:46:25 +08:00

101 lines
2.3 KiB
Go

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,
}
}