mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-04 21:02:27 +08:00
101 lines
2.3 KiB
Go
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,
|
|
}
|
|
}
|