rese = res(ult) + e(rror) - Streamline Go error handling with elegant result extraction.
Transform verbose error checking into clean, expressive code.
Traditional Go error handling:
num, err := getNumber()
if err != nil {
panic(err)
}
text, err := getText()
if err != nil {
panic(err)
}
result := fmt.Sprintf("%s: %d", text, num)With rese:
result := fmt.Sprintf("%s: %d", rese.V1(getText()), rese.V1(getNumber()))Clean, concise, and safe!
go get github.com/yyle88/rese// V series - Check error and return value
result := rese.V1(getValue()) // Returns value and panics when error is present
a, b := rese.V2(getTwoValues()) // Returns two values and panics when error is present// P series - Check error AND ensure pointer is non-nil
ptr := rese.P1(getPointer()) // Returns non-nil pointer and panics when error/nil is present// C series - Check error AND ensure value is non-zero
count := rese.C1(getCount()) // Returns non-zero value and panics when error/zero is presentrese provides multiple function series (0-9 parameters each) for different validation needs:
| Series | Purpose | Example Usage |
|---|---|---|
| V (Value) | Check error, return value(s) | rese.V1(getValue()) |
| P (Pointer) | Check error + pointer non-nil | rese.P1(getPointer()) |
| C (Comparable) | Check error + value non-zero | rese.C1(getCount()) |
| A (Array/Slice) | Check error + slice has elements | rese.A1(getItems()) |
| M (Map) | Check error + map has entries | rese.M1(getMapping()) |
| F (Function) | Execute function + V series | rese.F1(getValue) |
| R (Run pointer) | Execute function + P series | rese.R1(getPointer) |
Handle (value, bool) return patterns:
| Series | Purpose | Example Usage |
|---|---|---|
| resb.V | Check bool, return value(s) | resb.V1(getValue()) |
| resb.P | Check bool + pointer non-nil | resb.P1(getPointer()) |
| resb.C | Check bool + value non-zero | resb.C1(getCount()) |
package main
import (
"fmt"
"github.com/yyle88/rese"
)
// getValue simulates a function that returns a value with potential error
// Demonstrates error handling with V1 function
func getValue() (string, error) {
return "success-result", nil
}
// getNumber simulates a function that returns a numeric value with potential error
// Used to demonstrate V1 with different data types
func getNumber() (int, error) {
return 42, nil
}
// getTwoValues demonstrates function returning two values with potential error
// Shows V2 usage for multiple value extraction
func getTwoValues() (string, int, error) {
return "data", 100, nil
}
func main() {
// Example 1: Basic V1 usage - extracts value when no error
// When error is present, V1 panics
result := rese.V1(getValue())
fmt.Println("Result:", result)
// Example 2: V1 with numeric type
// Demonstrates V1 works with different data types
number := rese.V1(getNumber())
fmt.Println("Number:", number)
// Example 3: V2 usage - extracts two values when no error
// Shows handling of multiple return values
text, count := rese.V2(getTwoValues())
fmt.Println("Text:", text, "Count:", count)
// Example 4: Compact inline usage
// Demonstrates clean code without intermediate variables
message := fmt.Sprintf("Got %s with count %d", rese.V1(getValue()), rese.V1(getNumber()))
fmt.Println(message)
}β¬οΈ Source: Source
package main
import (
"fmt"
"github.com/yyle88/rese"
)
// Account represents a simple account data structure
// Used to demonstrate pointer validation with P1
type Account struct {
Name string
Age int
}
// getAccount simulates fetching account data
// Returns pointer to Account with potential error
func getAccount() (*Account, error) {
return &Account{Name: "Alice", Age: 30}, nil
}
// Config represents application configuration
// Used to demonstrate P series with different types
type Config struct {
Host string
Port int
}
// getConfig simulates fetching configuration
// Returns pointer to Config with potential error
func getConfig() (*Config, error) {
return &Config{Host: "localhost", Port: 8080}, nil
}
// getTwoPointers demonstrates function returning two pointers with potential error
// Shows P2 usage for multiple pointer validation
func getTwoPointers() (*Account, *Config, error) {
return &Account{Name: "Bob", Age: 25}, &Config{Host: "0.0.0.0", Port: 9090}, nil
}
func main() {
// Example 1: Basic P1 usage - validates pointer is non-nil
// Panics when error is present and when pointer is nil
account := rese.P1(getAccount())
fmt.Printf("Account: %s, Age: %d\n", account.Name, account.Age)
// Example 2: P1 with different type
// Demonstrates P1 works with various pointer types
config := rese.P1(getConfig())
fmt.Printf("Config: %s:%d\n", config.Host, config.Port)
// Example 3: P2 usage - validates two pointers
// Shows handling of multiple pointer return values
acc, cfg := rese.P2(getTwoPointers())
fmt.Printf("Account: %s, Config: %s:%d\n", acc.Name, cfg.Host, cfg.Port)
// Example 4: Compact inline usage with pointer access
// Demonstrates clean code without intermediate variables
message := fmt.Sprintf("Account %s is %d years old", rese.P1(getAccount()).Name, rese.P1(getAccount()).Age)
fmt.Println(message)
}β¬οΈ Source: Source
package main
import (
"fmt"
"github.com/yyle88/rese"
"github.com/yyle88/rese/resb"
)
// lookupValue simulates a map lookup operation
// Returns value with bool flag indicating success
func lookupValue(key string) (string, bool) {
data := map[string]string{
"name": "Alice",
"city": "Shanghai",
"role": "Engineer",
}
value, ok := data[key]
return value, ok
}
// lookupNumber simulates retrieving a numeric value
// Returns number with bool flag indicating presence
func lookupNumber(key string) (int, bool) {
data := map[string]int{
"age": 30,
"score": 95,
"count": 100,
}
value, ok := data[key]
return value, ok
}
// getAccountPointer simulates fetching account data with bool flag
// Returns pointer with bool flag instead of error
func getAccountPointer() (*struct{ Name string }, bool) {
return &struct{ Name string }{Name: "Bob"}, true
}
// getItems demonstrates slice return with error
// Shows A1 usage for slice validation
func getItems() ([]string, error) {
return []string{"apple", "banana", "orange"}, nil
}
// getScores demonstrates map return with error
// Shows M1 usage for map validation
func getScores() (map[string]int, error) {
return map[string]int{"math": 95, "english": 88}, nil
}
func main() {
// Example 1: resb.V1 usage - checks bool and returns value
// Panics when bool is false
name := resb.V1(lookupValue("name"))
fmt.Println("Name:", name)
// Example 2: resb.V1 with numeric type
// Demonstrates resb works with different data types
age := resb.V1(lookupNumber("age"))
fmt.Println("Age:", age)
// Example 3: resb.P1 usage - validates pointer and bool
// Combines pointer check with bool validation
account := resb.P1(getAccountPointer())
fmt.Println("Account:", account.Name)
// Example 4: A1 usage - validates slice has elements
// Panics when error is present and when slice is nil/has no elements
items := rese.A1(getItems())
fmt.Println("Items:", items)
// Example 5: M1 usage - validates map has entries
// Panics when error is present and when map is nil/has no entries
scores := rese.M1(getScores())
fmt.Println("Scores:", scores)
// Example 6: Compact inline usage with resb
// Demonstrates clean map lookup without intermediate variables
message := fmt.Sprintf("%s from %s works as %s",
resb.V1(lookupValue("name")),
resb.V1(lookupValue("city")),
resb.V1(lookupValue("role")))
fmt.Println(message)
}β¬οΈ Source: Source
Check non-zero integer:
userID := rese.C1(getUserID()) // Returns 12345, panics if error or zero
fmt.Println("User ID:", userID)Validate multiple comparable values:
id, status := rese.C2(getIDAndStatus()) // Both must be non-zeroEnsure slice has elements:
items := rese.A1(getItems()) // Returns []string{"apple", "banana", "orange"}
fmt.Println("Items:", items)Ensure map has entries:
scores := rese.M1(getScores()) // Returns map[string]int{"math": 95, "english": 88}
fmt.Println("Scores:", scores)Execute function and validate:
data := rese.F1(fetchData) // Executes fetchData(), returns "data loaded"
fmt.Println(data)Execute with multiple returns:
user, config := rese.F2(initialize) // Executes and validates two valuesHandle map lookup results:
value := resb.V1(lookupValue()) // Returns "found", panics if not found
fmt.Println("Value:", value)Check bool flag:
config := resb.V1(m["key"]) // Panics if key doesn't exist| Function | Description |
|---|---|
V1[T1](v1 T1, err) T1 |
Check error, return 1 value |
V2[T1,T2](v1 T1, v2 T2, err) (T1,T2) |
Check error, return 2 values |
V3 ~ V9 |
Check error, return 3-9 values |
Note: For
V0(err error)with no return value, consider using must package instead.
| Function | Description |
|---|---|
P1[T1](v1 *T1, err) *T1 |
Check error + pointer non-nil, return 1 pointer |
P2[T1,T2](v1 *T1, v2 *T2, err) (*T1,*T2) |
Check error + pointers non-nil, return 2 pointers |
P3 ~ P9 |
Check error + pointers non-nil, return 3-9 pointers |
Note:
P0is same asV0, use must package for simple error checking.
| Function | Description |
|---|---|
C1[T1 comparable](v1 T1, err) T1 |
Check error + value non-zero, return 1 value |
C2[T1,T2 comparable](v1 T1, v2 T2, err) (T1,T2) |
Check error + values non-zero, return 2 values |
C3 ~ C9 |
Check error + values non-zero, return 3-9 values |
Note:
C0is same asV0, use must package for simple error checking.
| Function | Description |
|---|---|
A1[T1](v1 []T1, err) []T1 |
Check error + slice has elements, return 1 slice |
A2[T1,T2](v1 []T1, v2 []T2, err) ([]T1,[]T2) |
Check error + slices have elements, return 2 slices |
A3 ~ A9 |
Check error + slices have elements, return 3-9 slices |
Note:
A0is same asV0, use must package for simple error checking.
| Function | Description |
|---|---|
M1[K1,V1](m1 map[K1]V1, err) map[K1]V1 |
Check error + map has entries, return 1 map |
M2[K1,K2,V1,V2](m1 map[K1]V1, m2 map[K2]V2, err) (map[K1]V1, map[K2]V2) |
Check error + maps have entries, return 2 maps |
M3 ~ M9 |
Check error + maps have entries, return 3-9 maps |
Note:
M0is same asV0, use must package for simple error checking.
| Function | Description |
|---|---|
F1[T1](run func() (T1, error)) T1 |
Execute function, apply V1 validation |
F2[T1,T2](run func() (T1, T2, error)) (T1,T2) |
Execute function, apply V2 validation |
F3 ~ F9 |
Execute function, apply V3-V9 validation |
Note:
F0is same asV0, use must package for simple error checking.
| Function | Description |
|---|---|
R1[T1](run func() (*T1, error)) *T1 |
Execute function, apply P1 validation |
R2[T1,T2](run func() (*T1, *T2, error)) (*T1,*T2) |
Execute function, apply P2 validation |
R3 ~ R9 |
Execute function, apply P3-P9 validation |
Note:
R0is same asV0, use must package for simple error checking.
The resb subpackage handles functions that return (value, bool) instead of (value, error).
// Map lookup - returns (value, bool)
func lookupConfig(key string) (string, bool) {
cfg := map[string]string{"host": "localhost", "port": "8080"}
return cfg[key]
}
// Using resb.V1 to handle (value, bool) results
config := resb.V1(lookupConfig("host")) // Panics if key not foundExplore more error handling packages in this ecosystem:
- must - Must-style assertions with rich type support and detailed error context
- rese - Result extraction with panic, focused on safe value unwrapping (this project)
- done - Simple, focused error handling with method chaining
- sure - Generates code that creates custom validation methods
Each package targets different use cases, from quick prototyping to production systems with comprehensive error handling.
MIT License. See LICENSE.
Contributions are welcome! Report bugs, suggest features, and contribute code:
- π Found a mistake? Open an issue on GitHub with reproduction steps
- π‘ Have a feature idea? Create an issue to discuss the suggestion
- π Documentation confusing? Report it so we can improve
- π Need new features? Share the use cases to help us understand requirements
- β‘ Performance issue? Help us optimize through reporting slow operations
- π§ Configuration problem? Ask questions about complex setups
- π’ Follow project progress? Watch the repo to get new releases and features
- π Success stories? Share how this package improved the workflow
- π¬ Feedback? We welcome suggestions and comments
New code contributions, follow this process:
- Fork: Fork the repo on GitHub (using the webpage UI).
- Clone: Clone the forked project (
git clone https://github.com/yourname/rese.git). - Navigate: Navigate to the cloned project (
cd rese) - Branch: Create a feature branch (
git checkout -b feature/xxx). - Code: Implement the changes with comprehensive tests
- Testing: (Golang project) Ensure tests pass (
go test ./...) and follow Go code style conventions - Documentation: Update documentation to support client-facing changes and use significant commit messages
- Stage: Stage changes (
git add .) - Commit: Commit changes (
git commit -m "Add feature xxx") ensuring backward compatible code - Push: Push to the branch (
git push origin feature/xxx). - PR: Open a merge request on GitHub (on the GitHub webpage) with detailed description.
Please ensure tests pass and include relevant documentation updates.
Welcome to contribute to this project via submitting merge requests and reporting issues.
Project Support:
- β Give GitHub stars if this project helps you
- π€ Share with teammates and (golang) programming friends
- π Write tech blogs about development tools and workflows - we provide content writing support
- π Join the ecosystem - committed to supporting open source and the (golang) development scene
Have Fun Coding with this package! πππ