Done lets you focus on the business logic without repetitive if err != nil patterns.
When you write logic:
if err := run(); err != nil {
panic(err)
}Then you can use done:
done.Done(run())- Eliminates boilerplate: Replace verbose
if err != nilblocks with concise function calls - Type-safe validation: Built with Go generics to provide compile-time type checking and IDE support
- Chainable operations: Link validation calls into clean, readable code flow
- Multiple return types: Handle functions returning values, pointers, slices, maps, and more
- Rich assertions: Specialized validators covering numbers, strings, booleans, and collections
- Focus on logic: Keep error handling lightweight so business logic stands out
go get github.com/yyle88/doneThis example demonstrates three approaches: classic step-based validation, chained validation, and compact chained validation using done.
package main
import (
"fmt"
"github.com/yyle88/done"
)
func main() {
// Classic approach with explicit checks
fmt.Println(WithClassicErrorHandling())
// Chained approach with done.VCE
fmt.Println(WithChainedErrorHandling())
// Compact chained approach
fmt.Println(WithCompactChainedHandling())
}
// WithClassicErrorHandling demonstrates classic validation with explicit checks.
// Pros: Distinct and simple to debug; Cons: Verbose code.
func WithClassicErrorHandling() string {
service, err := NewService()
if err != nil {
panic(err) // Handle errors at each step
}
client, err := service.GetClient()
if err != nil {
panic(err)
}
response, err := client.GetResponse()
if err != nil {
panic(err)
}
return response.Message
}
// WithChainedErrorHandling uses done.VCE to streamline validation in a chained fashion.
// Pros: Compact code; Cons: Debugging stacks can be challenging.
func WithChainedErrorHandling() string {
service := done.VCE(NewService()).Nice()
client := done.VCE(service.GetClient()).Nice()
response := done.VCE(client.GetResponse()).Nice()
return response.Message
}
// WithCompactChainedHandling shows the most compact form of chained validation.
// Pros: Concise code; Cons: Debugging is challenging.
func WithCompactChainedHandling() string {
return done.VCE(done.VCE(done.VCE(
NewService(),
).Nice().GetClient(),
).Nice().GetResponse(),
).Nice().Message
}
// Service represents the main service in the chain.
type Service struct{}
// NewService creates a new Service instance.
func NewService() (*Service, error) {
return &Service{}, nil
}
// GetClient returns a Client instance from this service.
func (s *Service) GetClient() (*Client, error) {
return &Client{}, nil
}
// Client represents the intermediate client in the chain.
type Client struct{}
// GetResponse returns the Response containing the result message.
func (c *Client) GetResponse() (*Response, error) {
return &Response{
Message: "success", // Simulated success message
}, nil
}
// Response represents the response containing the result.
type Response struct {
Message string // Result message
}β¬οΈ Source: Source
This example demonstrates two approaches to error handling: classic step-based validation and compact chained validation using done.
package main
import (
"fmt"
"strconv"
"github.com/pkg/errors"
"github.com/yyle88/done"
)
func main() {
// Classic approach with explicit checks
fmt.Println(WithClassicErrorHandling())
// Compact chained approach
fmt.Println(WithCompactChainedHandling())
}
// WithClassicErrorHandling demonstrates classic validation with explicit checks.
// Pros: Distinct and explicit; Cons: Verbose code.
func WithClassicErrorHandling() int64 {
text, err := webFetch()
if err != nil {
panic(err) // Handle error at each step
}
num, err := parseNum(text)
if err != nil {
panic(err)
}
if num <= 0 {
panic(errors.New("num must be positive"))
}
return num
}
// WithCompactChainedHandling uses done.VCE and done.VNE to provide concise validation.
// Pros: Compact code; Cons: Debugging can be challenging.
func WithCompactChainedHandling() int64 {
// Chain methods to fetch, parse, and validate the value
return done.VNE(
parseNum(
done.VCE(webFetch()).Nice(),
),
).Gt(0)
}
// webFetch simulates fetching a string value from a remote source.
func webFetch() (string, error) {
return "100", nil // Simulated data fetch
}
// parseNum converts a string to an int64 value.
func parseNum(text string) (int64, error) {
return strconv.ParseInt(text, 10, 64)
}β¬οΈ Source: Source
This example demonstrates using done.P2 to validate and extract multiple pointer results.
package main
import (
"fmt"
"github.com/yyle88/done"
)
func main() {
// Classic approach: check results with explicit validation
WithClassicErrorHandling()
// Compact approach: use done.P2 to reduce boilerplate
WithCompactErrorHandling()
}
// WithClassicErrorHandling demonstrates classic validation with explicit checks.
// Pros: Explicit and distinct; Cons: Verbose code.
func WithClassicErrorHandling() {
account, config, err := fetchAccountAndConfig()
if err != nil {
panic(err) // Check each step
}
if account == nil {
panic("account is nil") // Validate account exists
}
if config == nil {
panic("config is nil") // Validate config exists
}
fmt.Println(account, config) // Print both account and config
}
// WithCompactErrorHandling uses done.P2 to streamline validation.
// Pros: Concise code; Cons: Validation is implicit.
func WithCompactErrorHandling() {
account, config := done.P2(fetchAccountAndConfig()) // done.P2 handles checks
fmt.Println(account, config) // Print both account and config
}
// Account represents an account in the system.
type Account struct {
ID int // Account ID
Name string // Account name
}
// Config represents configuration settings.
type Config struct {
Timeout int // Timeout in seconds
Region string // Service region
}
// fetchAccountAndConfig simulates fetching account and config data.
func fetchAccountAndConfig() (*Account, *Config, error) {
account := &Account{ID: 1, Name: "Alice"}
config := &Config{Timeout: 30, Region: "us-west"}
return account, config, nil
}β¬οΈ Source: Source
| Type | Description |
|---|---|
Ve[V any] |
Wraps any value with error. Provides Done, Must, Soft to handle errors |
Vpe[V any] |
Wraps pointer with error. Validates non-nil with Sure, Nice, Full |
Vce[V comparable] |
Wraps comparable value with error. Compares values using Same, Diff, Equals |
Vbe |
Wraps boolean with error. Asserts true/false with TRUE, FALSE, OK, NO |
Vae[V any] |
Wraps slice with error. Checks emptiness and length with Some, Have, Length |
Vme[K, V] |
Wraps map with error. Validates size and content with Nice, Size, Len |
| Function | Description |
|---|---|
Done |
Panics with logging if error exists |
Must |
Ensures error is nil, returns value on success |
Soft |
Logs warning without panic, continues execution |
Fata |
Logs fatal error and terminates program |
| Group | Functions | Description |
|---|---|---|
| Errors | Done, Must, Soft |
Handle errors with panic/warning based on stage |
| Non-Zero Validation | Sure, Nice, Some |
Validate non-zero values and return them |
| Non-Zero Assertion | Good, Fine, Safe |
Assert non-zero values without returning |
| Zero Value Checking | Zero, None, Void |
Validate values are zero/absent |
| Value Comparisons | Same, Diff, Is, Equals |
Compare values checking matches/differences |
| Type | Purpose | Methods |
|---|---|---|
Vce |
Comparable values | Same, Diff, Is, Equals - value comparison |
Vse |
String operations | HasPrefix, HasSuffix, Contains - substring checks |
Vne |
Numeric comparisons | Gt, Lt, Gte, Lte - range validation |
Vbe |
Boolean assertions | TRUE, FALSE, YES, NO, OK - true/false checks |
Vae |
Slice validation | Sure, Some, Have, Length - emptiness and size checks |
Vme |
Map validation | Nice, Some, Size, Len - map size and content checks |
Simple error check:
done.Done(run())Return value with error check:
result := done.V1(fetchData())Multiple return values:
v1, v2 := done.V2(getTwoValues())Single pointer validation:
ptr := done.P1(getPointer())Multiple pointer validation:
ptr1, ptr2 := done.P2(getTwoPointers())Check values are the same:
value := done.VCE(getValue()).Same(expected)Check values are different:
value := done.VCE(getValue()).Diff(unwanted)Validate value exceeds threshold:
num := done.VNE(getNumber()).Gt(0)Less than validation:
num := done.VNE(getNumber()).Lt(100)Ensure boolean is true:
done.VBE(checkCondition()).TRUE()Ensure boolean is false:
done.VBE(checkCondition()).FALSE()Ensure slice has elements:
items := done.VAE(getSlice()).Some()Check slice length:
items := done.VAE(getSlice()).Length(3)Ensure map has content:
data := done.VME(getMap()).Nice()Check map size:
data := done.VME(getMap()).Size(5)The Done package brings a robust approach to error handling in Go. Through eliminating repetitive error checks, it lets you write clean, maintainable code. When building prototypes and production systems, Done helps you focus on what matters: the business logic.
Test it out and let us know what you think!
Explore 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
- done - Simple, focused error handling (this project)
- 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/repo-name.git). - Navigate: Navigate to the cloned project (
cd repo-name) - 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! πππ