feat: add try-catch-finally implementation

This commit is contained in:
dudaodong
2024-11-04 14:46:25 +08:00
parent 840ea8f3c5
commit 8bbae69175
7 changed files with 475 additions and 70 deletions

View File

@@ -1,51 +1,51 @@
-----BEGIN rsa private key-----
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
-----END rsa private key-----

View File

@@ -1,14 +1,14 @@
-----BEGIN rsa public key-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsZoYOi7lxZ3zk4zTa/nv
lQzPeXNBthaUpAJmC1b2/ldmglZ8ARGoVv45VCjG1yKO47SiN8ijcA///o/EawGZ
8mJHv8WsPUBxzUF2OQHSZ/kHlbi1vZsbGXLcM9siBU79uqudbyqUm/9OkgnTPCUU
zOlaFtKGeyoDM4TBAX7ec8G8LWBdBAgNAaK/vP+iXuPHxLdKNMDDel67nLNYJ30K
C/fUbwHixn5yQLx4zVLF+rv3pUbQuTeEvS+N19Cg1/+5/xzGK+YYdO1ZH4qgubNB
u9C90wH0FhIuDDfswh8liZbjHcXsJ82QPdaxjbz1bSb8OToackMMocvJVI9ToxSB
dGvGoBk1mnLJRSab6nOD56+iRoGJmy6GTpD2I1ie1PHV1Y2TIjUESnxjgPigaYA5
i/MkXlD/1CtrDW6hsc0/WgCSD7ZGjNTduUwdwmd2es1XIqnamht+QJE1JTbBFLd9
r5zXQY/5W5nRQHBmWP5fVHy7a/wmF9N2ZpI/DYMarCRIVBsiMdsE62mq63haB6yw
jkVk+78TXtmXTTE8ts6XImt+m+0RY4lAd+UfHvyOe3dH2y5nGSHG4C8CXB264YdA
pZZjjvVZy5K3lsmmBB+4Kje1Rux36F76qEOvjZ2QvpJDTXSXOk1POu6aZc8N+XRu
vG7hmEPdF3xD68VPSZ5/gfcCAwEAAQ==
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsELqn9abxs7ZK81Ipbp5
+E/5SrOQycAalnRCES3YPOoAV3Ir+99WjEi9Ak4EYS3VrvgISSNiRx1tHDNpBlBq
GF+Mww8wAUmrcXsEndbHma/g3zHGueua9GK0l+hQJ/grkatykgD81gam/SPOMPnJ
SsoQlsTgM47ZHM35adiXqL/gDMZ70lQdB2+03WJXlvfYZWpHsXDqUkveEZbLgZST
36ax8ap+Ge2GoLlD1sNapRxMBH1PGNdzSdV7ZJmzQ3WmjwDAddLX73YE6vhR5tDA
XhrSweNPtIjUhGJsgkW9VTEQWeW9cZmFo/jYuvEDgBnZOh1DJe2BHx06Ymr8Zcgs
OBYddANsk750II8+qUnBekiJkpo0ldCK2VnsLoLM3YCf3Lk7VYuHP6KiCXyh6Fzb
Y1DTRHJRpMJYT8t5xyQis581DbRVPkcse3ig5KsQLe5XXbBBegVrQJpy1b440uZV
W2eSpStX5ZAfNVsU0ZPdI4/i6UNMEa6c7tf83S21Q0K6SEZ5PrfBJECRDxFzJWea
mwppHY8fdeItVk/cxBJ9XRyOyG9pJKMnOMFD++LzGP6uL5FKov7BSplOIMqsJzwh
4zkIjAhgbGVQZm17kg1xvF30c2fgijNEoSIuVWJzlQyQ9cmSaSmmi+SPmf/C/IcU
DF0nikERs1v58vNESvcZP80CAwEAAQ==
-----END rsa public key-----

View File

@@ -35,6 +35,7 @@ import (
- [XError_Info](#XError_Info)
- [XError_Error](#XError_Error)
- [TryUnwrap](#TryUnwrap)
- [TryCatch](#TryCatch)
<div STYLE="page-break-after: always;"></div>
@@ -167,12 +168,12 @@ import (
func main() {
err1 := xerror.New("error").With("level", "high")
err2 := err1.Wrap(errors.New("invalid username"))
err2 := err1.Wrap(errors.New("invalid username"))
fmt.Println(err2.Error())
fmt.Println(err2.Error())
// Output:
// error: invalid username
// Output:
// error: invalid username
}
```
@@ -489,3 +490,56 @@ func main() {
// true
}
```
### <span id="TryCatch">TryCatch</span>
<p>简单实现的java风格异常处理try-catch-finally。try catch不符合go错误处理风格谨慎使用。</p>
<b>函数签名:</b>
```go
func NewTryCatch(ctx context.Context) *TryCatch
func (tc *TryCatch) Try(tryFunc func(ctx context.Context) error) *TryCatch
func (tc *TryCatch) Catch(catchFunc func(ctx context.Context, err error)) *TryCatch
func (tc *TryCatch) Finally(finallyFunc func(ctx context.Context)) *TryCatch
func (tc *TryCatch) Do()
```
<b>示例:<span style="float:right;display:inline-block">[运行](todo)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
calledFinally := false
calledCatch := false
tc := xerror.NewTryCatch(context.Background())
tc.Try(func(ctx context.Context) error {
return errors.New("error in try block")
}).Catch(func(ctx context.Context, err error) {
calledCatch = true
// Error in try block at /path/xxx.go:{line_number} - Cause: error message
// fmt.Println(err.Error())
}).Finally(func(ctx context.Context) {
calledFinally = true
}).Do()
fmt.Println(calledCatch)
fmt.Println(calledFinally)
// Output:
// true
// true
}
```

View File

@@ -35,6 +35,7 @@ import (
- [XError_Info](#XError_Info)
- [XError_Error](#XError_Error)
- [TryUnwrap](#TryUnwrap)
- [TryCatch](#TryCatch)
<div STYLE="page-break-after: always;"></div>
@@ -166,12 +167,12 @@ import (
func main() {
err1 := xerror.New("error").With("level", "high")
err2 := err1.Wrap(errors.New("invalid username"))
err2 := err1.Wrap(errors.New("invalid username"))
fmt.Println(err2.Error())
fmt.Println(err2.Error())
// Output:
// error: invalid username
// Output:
// error: invalid username
}
```
@@ -487,3 +488,56 @@ func main() {
// true
}
```
### <span id="TryCatch">TryCatch</span>
<p>Simple simulation of Java-style try-catch. It does not align with Go's error-handling philosophy. It is recommended to use it with caution.</p>
<b>Signature:</b>
```go
func NewTryCatch(ctx context.Context) *TryCatch
func (tc *TryCatch) Try(tryFunc func(ctx context.Context) error) *TryCatch
func (tc *TryCatch) Catch(catchFunc func(ctx context.Context, err error)) *TryCatch
func (tc *TryCatch) Finally(finallyFunc func(ctx context.Context)) *TryCatch
func (tc *TryCatch) Do()
```
<b>Example:<span style="float:right;display:inline-block;">[Run](todo)</span></b>
```go
package main
import (
"fmt"
"github.com/duke-git/lancet/v2/xerror"
)
func main() {
calledFinally := false
calledCatch := false
tc := xerror.NewTryCatch(context.Background())
tc.Try(func(ctx context.Context) error {
return errors.New("error message ")
}).Catch(func(ctx context.Context, err error) {
calledCatch = true
// Error in try block at /path/xxx.go:{line_number} - Cause: error message
// fmt.Println(err.Error())
}).Finally(func(ctx context.Context) {
calledFinally = true
}).Do()
fmt.Println(calledCatch)
fmt.Println(calledFinally)
// Output:
// true
// true
}
```

100
xerror/trycatch.go Normal file
View 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,
}
}

172
xerror/trycatch_test.go Normal file
View File

@@ -0,0 +1,172 @@
package xerror
import (
"context"
"errors"
"testing"
"github.com/duke-git/lancet/v2/internal"
)
func TestTryCatchSuccess(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestTryCatchSuccess")
counter := 0
calledCatch := false
calledFinally := false
tc := NewTryCatch(context.Background())
tc.Try(func(ctx context.Context) error {
counter++
return nil
}).Catch(func(ctx context.Context, err error) {
calledCatch = true
t.Errorf("Catch should not be called")
}).Finally(func(ctx context.Context) {
calledFinally = true
}).Do()
assert.Equal(1, counter)
assert.Equal(false, calledCatch)
assert.Equal(true, calledFinally)
}
func TestTryCatchError(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestTryCatchError")
var catchedError error
calledFinally := false
tc := NewTryCatch(context.Background())
tc.Try(func(ctx context.Context) error {
return errors.New("error")
}).Catch(func(ctx context.Context, err error) {
catchedError = errors.New("catched error")
}).Finally(func(ctx context.Context) {
calledFinally = true
}).Do()
assert.Equal("catched error", catchedError.Error())
assert.Equal(true, calledFinally)
}
func TestTryCatchPanic(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestTryCatchPanic")
var catchedError error
calledFinally := false
tc := NewTryCatch(context.Background())
tc.Try(func(ctx context.Context) error {
panic("panic info")
}).Catch(func(ctx context.Context, err error) {
catchedError = errors.New("catched error")
}).Finally(func(ctx context.Context) {
calledFinally = true
}).Do()
assert.Equal("catched error", catchedError.Error())
assert.Equal(true, calledFinally)
}
func TestTryCatchContextCancelled(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestTryCatchContextCancelled")
var catchedError error
calledFinally := false
ctx, cancel := context.WithCancel(context.Background())
cancel()
tc := NewTryCatch(ctx)
tc.Try(func(ctx context.Context) error {
return nil
}).Catch(func(ctx context.Context, err error) {
catchedError = errors.New("catched error")
}).Finally(func(ctx context.Context) {
calledFinally = true
}).Do()
assert.Equal("catched error", catchedError.Error())
assert.Equal(true, calledFinally)
}
func TestTryCatchContextTimeout(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestTryCatchContextTimeout")
var catchedError error
calledFinally := false
ctx, cancel := context.WithTimeout(context.Background(), 0)
defer cancel()
tc := NewTryCatch(ctx)
tc.Try(func(ctx context.Context) error {
return nil
}).Catch(func(ctx context.Context, err error) {
catchedError = errors.New("catched error")
}).Finally(func(ctx context.Context) {
calledFinally = true
}).Do()
assert.Equal("catched error", catchedError.Error())
assert.Equal(true, calledFinally)
}
func TestTryCatchContextError(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestTryCatchContextError")
var catchedError error
calledFinally := false
ctx, cancel := context.WithTimeout(context.Background(), 0)
defer cancel()
tc := NewTryCatch(ctx)
tc.Try(func(ctx context.Context) error {
return errors.New("error")
}).Catch(func(ctx context.Context, err error) {
catchedError = errors.New("catched error")
}).Finally(func(ctx context.Context) {
calledFinally = true
}).Do()
assert.Equal("catched error", catchedError.Error())
assert.Equal(true, calledFinally)
}
func TestTryCatchNoCatch(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestTryCatchNoCatch")
calledFinally := false
tc := NewTryCatch(context.Background())
tc.Try(func(ctx context.Context) error {
return errors.New("error")
}).Finally(func(ctx context.Context) {
calledFinally = true
}).Do()
assert.Equal(true, calledFinally)
}

View File

@@ -1,6 +1,7 @@
package xerror
import (
"context"
"errors"
"fmt"
"reflect"
@@ -61,7 +62,7 @@ func ExampleXError_StackTrace() {
// Output:
// github.com/duke-git/lancet/v2/xerror.ExampleXError_StackTrace
// 52
// 53
// true
}
@@ -154,3 +155,27 @@ func ExampleTryUnwrap() {
// 42
// true
}
func ExampleTryCatch() {
calledFinally := false
calledCatch := false
tc := NewTryCatch(context.Background())
tc.Try(func(ctx context.Context) error {
return errors.New("error message")
}).Catch(func(ctx context.Context, err error) {
calledCatch = true
// Error in try block at /path/xxx.go:174 - Cause: error message
// fmt.Println(err.Error())
}).Finally(func(ctx context.Context) {
calledFinally = true
}).Do()
fmt.Println(calledCatch)
fmt.Println(calledFinally)
// Output:
// true
// true
}