Skip to content

Commit

Permalink
增加样例
Browse files Browse the repository at this point in the history
  • Loading branch information
yangyile committed Nov 19, 2024
1 parent 545fdd6 commit 19bf01d
Show file tree
Hide file tree
Showing 5 changed files with 284 additions and 9 deletions.
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 YANG-YI-LE

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
89 changes: 81 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,33 @@ This package introduces several types and functions that make error handling mor

### Example Usage

Here is an example code:

```go
package main

import (
"fmt"
"github.com/yyle88/done"
)

func main() {
xyz, err := NewXyz()
if err != nil {
panic(err) // Handle errors manually / 手动处理错误
}
abc, err := xyz.Abc()
if err != nil {
panic(err)
}
uvw, err := abc.Uvw()
if err != nil {
panic(err)
}
fmt.Println(uvw.Message)
}
```

Here is how you would use the package to handle errors in a typical Go application:

```go
Expand All @@ -48,23 +75,69 @@ import (
)

func main() {
cli := done.VCE(xxx.NewXx()).Nice()
res := done.VCE(cli.Abc()).Nice()
xyz := done.VCE(res.Xyz).Nice()
fmt.Println(xyz)
xyz := done.VCE(NewXyz()).Nice()
abc := done.VCE(xyz.Abc()).Nice()
uvw := done.VCE(abc.Uvw()).Nice()
fmt.Println(uvw.Message)
}
```

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

In this example, the errors are checked and handled inline, allowing you to chain function calls without cluttering the code with repetitive error checks.

### Chaining Operations

Here is an example code:

```go
package main

import (
"fmt"
"strconv"

"github.com/pkg/errors"
"github.com/yyle88/done"
)

func main() {
snu, err := fetch()
if err != nil {
panic(err) // Handle error manually / 手动处理错误
}
num, err := toInt(snu)
if err != nil {
panic(err)
}
if !(num > 0) {
panic(errors.New("num is not > 0"))
}
fmt.Println(num)
}
```

You can chain multiple function calls with error handling assertions in a single line:

```go
num := done.VCE(yyy(done.VCE(xxx()).Nice())).Gt(0)
package main

import (
"fmt"
"strconv"

"github.com/pkg/errors"
"github.com/yyle88/done"
)

func main() {
num := done.VNE( toInt( done.VCE(fetch()).Nice() ) ).Gt(0)
fmt.Println(num)
}
```

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.

## Usage Scenarios
Expand Down Expand Up @@ -98,9 +171,9 @@ The utility functions provided by **Done** are based on different approaches to

In cases where you need more complex logic, such as comparing values or checking conditions, you can use the following functions:

- **Vce (Comparable Errors)**: Check if two comparable values are the same or different using `Same`, `Diff`, `Is`, and `Equals`.
- **Vse (String Errors)**: Check if a string matches conditions like `HasPrefix`, `HasSuffix`, or `Contains`.
- **Vne (Numerical Errors)**: Check if a numeric value meets conditions like `Gt`, `Lt`, `Gte`, or `Lte`.
- **Vce (Comparable + Errors)**: Check if two comparable values are the same or different using `Same`, `Diff`, `Is`, and `Equals`.
- **Vse (String + Errors)**: Check if a string matches conditions like `HasPrefix`, `HasSuffix`, or `Contains`.
- **Vne (Numerical + Errors)**: Check if a numeric value meets conditions like `Gt`, `Lt`, `Gte`, or `Lte`.

## Conclusion

Expand Down
2 changes: 1 addition & 1 deletion README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package name "done" means function() return success. also means "assert".

most of the time we write a go code, we need to handle the error return value.

it wastes a lot of time and code lines.
while the error handling logic wastes a lot of time and code lines.

```
res, err := xxx()
Expand Down
107 changes: 107 additions & 0 deletions internal/demos/demo1/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package main

import (
"fmt"

"github.com/yyle88/done"
)

// This example demonstrates three approaches to error handling: manual, chained, and compact chained.
// The primary focus is showcasing how compact invocation can simplify error handling in appropriate contexts.
// 该示例展示了三种错误处理方式:手动、链式和紧凑链式,主要是演示如何在合适的情况下通过紧凑式调用简化错误处理。

func main() {
// Manual error handling
// 手动处理错误
fmt.Println(ManualErrorHandling())

// Chained error handling
// 链式处理错误
fmt.Println(ChainedErrorHandling())

// Compact chained error handling
// 紧凑链式处理错误
fmt.Println(CompactChainedHandling())
}

// ManualErrorHandling demonstrates step-by-step manual error handling.
// Pros: Clear and easy to debug; Cons: Verbose code.
// ManualErrorHandling 展示了逐步手动处理每一步错误的方式。
// 优点:清晰且便于调试;缺点:代码冗长。
func ManualErrorHandling() string {
xyz, err := NewXyz()
if err != nil {
panic(err) // Handle errors manually / 手动处理错误
}
abc, err := xyz.Abc()
if err != nil {
panic(err)
}
uvw, err := abc.Uvw()
if err != nil {
panic(err)
}
return uvw.Message
}

// ChainedErrorHandling uses `done.VCE` to streamline error handling in a chained manner.
// Pros: Cleaner code; Cons: Debugging error stacks can be challenging.
// ChainedErrorHandling 使用 `done.VCE` 以链式方式简化错误处理。
// 优点:代码更简洁;缺点:调试错误堆栈可能更困难。
func ChainedErrorHandling() string {
xyz := done.VCE(NewXyz()).Nice()
abc := done.VCE(xyz.Abc()).Nice()
uvw := done.VCE(abc.Uvw()).Nice()
return uvw.Message
}

// CompactChainedHandling represents the most compact form of chained error handling.
// Pros: Extremely concise; Cons: Error debugging is difficult.
// CompactChainedHandling 使用最紧凑的链式写法。
// 优点:代码极简;缺点:定位问题较难。
func CompactChainedHandling() string {
return done.VCE(done.VCE(done.VCE(
NewXyz(),
).Nice().Abc(),
).Nice().Uvw(),
).Nice().Message
}

// ----------------------------------------------------------------------
// Simulated business logic structures and methods for demonstration purposes.
// 以下部分仅为演示用途,模拟业务逻辑。
// ----------------------------------------------------------------------

// XyzType represents the first layer of the object hierarchy.
// XyzType 表示对象层次的第一层。
type XyzType struct{}

// NewXyz creates a new XyzType instance.
// NewXyz 创建一个新的 XyzType 实例。
func NewXyz() (*XyzType, error) {
return &XyzType{}, nil
}

// Abc returns the second-layer object, AbcType.
// Abc 返回第二层对象 AbcType。
func (xyz *XyzType) Abc() (*AbcType, error) {
return &AbcType{}, nil
}

// AbcType represents the second layer of the object hierarchy.
// AbcType 表示对象层次的第二层。
type AbcType struct{}

// Uvw returns the final object, UvwType, containing the result message.
// Uvw 返回最终的结果对象 UvwType,包含结果消息。
func (abc *AbcType) Uvw() (*UvwType, error) {
return &UvwType{
Message: "success", // Simulated success message / 模拟成功消息
}, nil
}

// UvwType represents the final object containing the result.
// UvwType 表示包含结果的最终对象。
type UvwType struct {
Message string
}
74 changes: 74 additions & 0 deletions internal/demos/demo2/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package main

import (
"fmt"
"strconv"

"github.com/pkg/errors"
"github.com/yyle88/done"
)

// This example demonstrates two approaches to error handling: manual and compact chained.
// Show how compact invocation simplifies error checking while keeping the logic concise.
// 该示例展示了两种错误处理方式:手动和紧凑链式。
// 示例强调了如何通过紧凑式调用简化错误检查并保持逻辑简洁。

func main() {
// Manual error handling example
// 手动处理错误示例
fmt.Println(ManualErrorHandling())

// Compact chained error handling example
// 紧凑链式处理错误示例
fmt.Println(CompactChainedHandling())
}

// ManualErrorHandling demonstrates step-by-step error checking and handling.
// Pros: Clear and explicit; Cons: Verbose code.
// ManualErrorHandling 展示了逐步的错误检查与处理。
// 优点:清晰且显式;缺点:代码较冗长。
func ManualErrorHandling() int64 {
snu, err := fetch()
if err != nil {
panic(err) // Handle error manually / 手动处理错误
}
num, err := toInt(snu)
if err != nil {
panic(err)
}
if !(num > 0) {
panic(errors.New("num is not > 0"))
}
return num
}

// CompactChainedHandling uses `done.VCE` and `done.VNE` for concise error handling.
// Pros: Minimalistic; Cons: Harder to debug if something goes wrong.
// CompactChainedHandling 使用 `done.VCE` 和 `done.VNE` 以简化错误处理。
// 优点:代码极简;缺点:如果出现问题,调试较困难。
func CompactChainedHandling() int64 {
// Chain methods to fetch, convert, and validate the value
// 链式调用方法获取、转换并验证值
return done.VNE(
toInt(
done.VCE(fetch()).Nice(),
),
).Gt(0)
}

// ----------------------------------------------------------------------
// The following functions simulate business logic for demonstration purposes.
// 以下函数仅为演示用途,模拟了业务逻辑。
// ----------------------------------------------------------------------

// fetch simulates fetching a string value.
// fetch 模拟获取字符串值。
func fetch() (string, error) {
return "100", nil // Simulated successful fetch / 模拟成功获取
}

// toInt converts a string to an int64 value.
// toInt 将字符串转换为 int64 值。
func toInt(s string) (int64, error) {
return strconv.ParseInt(s, 10, 64)
}

0 comments on commit 19bf01d

Please sign in to comment.