Skip to content

Commit

Permalink
添加简单的多返回值错误检查
Browse files Browse the repository at this point in the history
  • Loading branch information
yangyile committed Nov 20, 2024
1 parent 19bf01d commit d89127d
Show file tree
Hide file tree
Showing 11 changed files with 922 additions and 2 deletions.
89 changes: 89 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,95 @@ See [demo2](internal/demos/demo2/main.go)

This way, you can check if the error exists at each step and continue with the result without writing long error-handling logic.

### Example Usage

This section demonstrates how you can simplify error handling and result validation using the `done` package. By using `done.P1`, `done.P2`, and `done.P3`, you can reduce the complexity of your error checks and nil checks, making your code more readable.

#### Example 1: Checking Results from `run1()`

Before using `done.P1`, we would have to manually check the error and handle nil values for the result:

```go
a, err := run1()
if err != nil {
panic(err) // If an error occurs, trigger a panic
}
if a == nil {
panic("a is nil") // If 'a' is nil, trigger panic
}
fmt.Println(a) // Output the result
```

With `done.P1`, you can perform the same checks in a cleaner, more concise way:

```go
a := done.P1(run1()) // done.P1 handles error checking and nil validation
fmt.Println(a) // Output the result
```

#### Example 2: Handling Multiple Results from `run2()`

For functions that return multiple values, such as `run2()`, you can use a similar approach:

```go
a, b, err := run2()
if err != nil {
panic(err) // If an error occurs, trigger a panic
}
if a == nil {
panic("a is nil") // If 'a' is nil, trigger panic
}
if b == nil {
panic("b is nil") // If 'b' is nil, trigger panic
}
fmt.Println(a, b) // Output both 'a' and 'b'
```

With `done.P2`, the error handling and nil checks are simplified:

```go
a, b := done.P2(run2()) // done.P2 simplifies error checking and validation
fmt.Println(a, b) // Output both 'a' and 'b'
```

#### Example 3: Handling Multiple Results from `run3()`

For functions that return even more values, like `run3()`, you can extend this pattern:

```go
a, b, c, err := run3()
if err != nil {
panic(err) // If an error occurs, trigger a panic
}
if a == nil {
panic("a is nil") // If 'a' is nil, trigger panic
}
if b == nil {
panic("b is nil") // If 'b' is nil, trigger panic
}
if c == nil {
panic("c is nil") // If 'c' is nil, trigger panic
}
fmt.Println(a, b, c) // Output 'a', 'b', and 'c'
```

Using `done.P3` simplifies error handling and validation for multiple results:

```go
a, b, c := done.P3(run3()) // done.P3 simplifies error checking and validation
fmt.Println(a, b, c) // Output 'a', 'b', and 'c'
```

See [demo3](internal/demos/demo3/main.go)

This way you can avoid checking whether the return value has errors or null values, which is very convenient.

There are also these methods that can provide additional convenience.
`done.P1() - done.P9()`
`done.C1() - done.C9()`
`done.V1() - done.V9()`
This avoids always checking if there are errors in the return values.

## Usage Scenarios

This package is ideal for projects where:
Expand Down
12 changes: 12 additions & 0 deletions check_value.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,15 @@ func None[V comparable](v V) {
panic(errors.New("SHOULD BE NONE BUT NOT NONE"))
}
}

func Null[V *any](v any) {
if v != nil {
panic(errors.New("SHOULD BE NULL BUT IS FULL"))
}
}

func Full[V *any](v any) {
if v == nil {
panic(errors.New("SHOULD BE FULL BUT IS NULL"))
}
}
8 changes: 8 additions & 0 deletions check_vpe.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,11 @@ func (a *Vpe[V]) Zero() {
func (a *Vpe[V]) None() {
None(a.Done())
}

func (a *Vpe[V]) Null() {
Null(a.Done())
}

func (a *Vpe[V]) Full() {
Full(a.Done())
}
135 changes: 135 additions & 0 deletions internal/demos/demo3/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package main

import (
"fmt"

"github.com/yyle88/done"
)

func main() {
// Directly checking the result of run1 with error handling
// 使用直接方法检查 run1 的结果并处理错误
{
a, err := run1()
if err != nil {
panic(err) // If an error occurs, trigger a panic
// 如果发生错误,触发 panic
}
if a == nil {
panic("a is nil") // If 'a' is nil, trigger panic
// 如果 'a' 为 nil,触发 panic
}
fmt.Println(a) // Output the result
// 输出结果
}

// Using done.P1 for cleaner error handling and result validation
// 使用 done.P1 简化错误处理和结果验证
{
a := done.P1(run1()) // done.P1 handles error checking and nil validation
// done.P1 处理错误检查和 nil 验证
fmt.Println(a) // Output the result
// 输出结果
}

// Directly checking the result of run2 with error handling
// 使用直接方法检查 run2 的结果并处理错误
{
a, b, err := run2()
if err != nil {
panic(err) // If an error occurs, trigger a panic
// 如果发生错误,触发 panic
}
if a == nil {
panic("a is nil") // If 'a' is nil, trigger panic
// 如果 'a' 为 nil,触发 panic
}
if b == nil {
panic("b is nil") // If 'b' is nil, trigger panic
// 如果 'b' 为 nil,触发 panic
}
fmt.Println(a, b) // Output both 'a' and 'b'
// 输出 'a' 和 'b'
}

// Using done.P2 for more concise error handling and result validation
// 使用 done.P2 使错误处理和结果验证更简洁
{
a, b := done.P2(run2()) // done.P2 simplifies error checking and validation
// done.P2 简化了错误检查和验证
fmt.Println(a, b) // Output both 'a' and 'b'
// 输出 'a' 和 'b'
}

// Directly checking the result of run3 with error handling
// 使用直接方法检查 run3 的结果并处理错误
{
a, b, c, err := run3()
if err != nil {
panic(err) // If an error occurs, trigger a panic
// 如果发生错误,触发 panic
}
if a == nil {
panic("a is nil") // If 'a' is nil, trigger panic
// 如果 'a' 为 nil,触发 panic
}
if b == nil {
panic("b is nil") // If 'b' is nil, trigger panic
// 如果 'b' 为 nil,触发 panic
}
if c == nil {
panic("c is nil") // If 'c' is nil, trigger panic
// 如果 'c' 为 nil,触发 panic
}
fmt.Println(a, b, c) // Output 'a', 'b', and 'c'
// 输出 'a','b' 和 'c'
}

// Using done.P3 to simplify error handling and result validation for run3
// 使用 done.P3 简化 run3 的错误处理和结果验证
{
a, b, c := done.P3(run3()) // done.P3 simplifies error checking and validation
// done.P3 简化了错误检查和验证
fmt.Println(a, b, c) // Output 'a', 'b', and 'c'
// 输出 'a','b' 和 'c'
}
}

// --------------------------
// Simulated business logic
// --------------------------

// Defining mock types for demonstration with fields
// 为演示定义模拟类型并添加字段
type A struct {
ID int
Name string
}

type B struct {
Age int
City string
}

type C struct {
Price float64
Code string
}

// run1 simulates returning an instance of A and error
// run1 模拟返回 A 的实例和错误
func run1() (*A, error) {
return &A{ID: 1, Name: "Alice"}, nil
}

// run2 simulates returning instances of A and B, and error
// run2 模拟返回 A 和 B 的实例以及错误
func run2() (*A, *B, error) {
return &A{ID: 1, Name: "Alice"}, &B{Age: 30, City: "New York"}, nil
}

// run3 simulates returning instances of A, B, and C, and error
// run3 模拟返回 A, B 和 C 的实例以及错误
func run3() (*A, *B, *C, error) {
return &A{ID: 1, Name: "Alice"}, &B{Age: 30, City: "New York"}, &C{Price: 100.5, Code: "XYZ123"}, nil
}
95 changes: 95 additions & 0 deletions nc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package done

func C0(err error) {
Must(err)
}

func C1[T1 comparable](v1 T1, err error) T1 {
Must(err)
Nice(v1)
return v1
}

func C2[T1, T2 comparable](v1 T1, v2 T2, err error) (T1, T2) {
Must(err)
Nice(v1)
Nice(v2)
return v1, v2
}

func C3[T1, T2, T3 comparable](v1 T1, v2 T2, v3 T3, err error) (T1, T2, T3) {
Must(err)
Nice(v1)
Nice(v2)
Nice(v3)
return v1, v2, v3
}

func C4[T1, T2, T3, T4 comparable](v1 T1, v2 T2, v3 T3, v4 T4, err error) (T1, T2, T3, T4) {
Must(err)
Nice(v1)
Nice(v2)
Nice(v3)
Nice(v4)
return v1, v2, v3, v4
}

func C5[T1, T2, T3, T4, T5 comparable](v1 T1, v2 T2, v3 T3, v4 T4, v5 T5, err error) (T1, T2, T3, T4, T5) {
Must(err)
Nice(v1)
Nice(v2)
Nice(v3)
Nice(v4)
Nice(v5)
return v1, v2, v3, v4, v5
}

func C6[T1, T2, T3, T4, T5, T6 comparable](v1 T1, v2 T2, v3 T3, v4 T4, v5 T5, v6 T6, err error) (T1, T2, T3, T4, T5, T6) {
Must(err)
Nice(v1)
Nice(v2)
Nice(v3)
Nice(v4)
Nice(v5)
Nice(v6)
return v1, v2, v3, v4, v5, v6
}

func C7[T1, T2, T3, T4, T5, T6, T7 comparable](v1 T1, v2 T2, v3 T3, v4 T4, v5 T5, v6 T6, v7 T7, err error) (T1, T2, T3, T4, T5, T6, T7) {
Must(err)
Nice(v1)
Nice(v2)
Nice(v3)
Nice(v4)
Nice(v5)
Nice(v6)
Nice(v7)
return v1, v2, v3, v4, v5, v6, v7
}

func C8[T1, T2, T3, T4, T5, T6, T7, T8 comparable](v1 T1, v2 T2, v3 T3, v4 T4, v5 T5, v6 T6, v7 T7, v8 T8, err error) (T1, T2, T3, T4, T5, T6, T7, T8) {
Must(err)
Nice(v1)
Nice(v2)
Nice(v3)
Nice(v4)
Nice(v5)
Nice(v6)
Nice(v7)
Nice(v8)
return v1, v2, v3, v4, v5, v6, v7, v8
}

func C9[T1, T2, T3, T4, T5, T6, T7, T8, T9 comparable](v1 T1, v2 T2, v3 T3, v4 T4, v5 T5, v6 T6, v7 T7, v8 T8, v9 T9, err error) (T1, T2, T3, T4, T5, T6, T7, T8, T9) {
Must(err)
Nice(v1)
Nice(v2)
Nice(v3)
Nice(v4)
Nice(v5)
Nice(v6)
Nice(v7)
Nice(v8)
Nice(v9)
return v1, v2, v3, v4, v5, v6, v7, v8, v9
}
Loading

0 comments on commit d89127d

Please sign in to comment.