Skip to content

yyle88/sure

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

52 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

GitHub Workflow Status (branch) GoDoc Coverage Status Supported Go Versions GitHub Release Go Report Card

sure: Add Assertions and Crash Handling to Existing Go Code

sure enhances existing Go code with assertions and crash handling. It asserts conditions and crashes when issues happen, improving issue management in code without adding repetitive checks.


CHINESE README

δΈ­ζ–‡θ―΄ζ˜Ž

CREATION_IDEAS

CREATION_IDEAS


Introduction

sure is a code generation package that transforms existing Go code into assertion-enhanced versions. Instead of adding repetitive checks throughout the codebase, sure generates wrapping code with built-in assertion logic, making issue detection and handling seamless.

The package provides three distinct generators, each serving different code transformation needs:

  • sure_cls_gen: Creates assertion-enabled class wrappers
  • sure_pkg_gen: Generates assertion-enabled package wrappers
  • cls_stub_gen: Produces singleton wrapping functions

Core Features

🎯 Three Assertion Modes

  • Must: Crash on issues (panic-based)
  • Soft: Log warnings and continue execution
  • Omit: Silent mode - ignore issues

⚑ Automatic Code Generation

  • Transform existing code without modification
  • Generate type-safe wrappers with assertions
  • Preserve function signatures and documentation

πŸ”§ Flexible Integration

  • Works with existing Go projects
  • No runtime dependencies in generated code
  • Compatible with standard Go packages

πŸ“¦ Multiple Generation Strategies

  • Class-based: Wrap object methods
  • Package-based: Wrap package functions
  • Singleton-based: Wrap instance methods as package functions

Benefits of sure

Problem: Repetitive Issue Handling

Standard issue handling in Go requires repetitive checks:

result, err := SomeOperation()
if err != nil {
    log.Printf("operation failed: %v", err)
    return err
}

data, err := AnotherOperation(result)
if err != nil {
    log.Printf("another operation failed: %v", err)
    return err
}

This becomes verbose and repetitive across large codebases.

Solution: Generated Assertion Wrappers

With sure, generate assertion-enabled wrappers:

// Source function
func ReadConfig(path string) (*Config, error)

// Generated wrapping (Must mode)
func (s *SureConfig) ReadConfig(path string) *Config

// Usage - crashes on issues, no manual checks needed
config := sureConfig.ReadConfig("config.json")

The generated code handles assertions, enabling clean business logic.


Package Overview

sure_cls_gen: Assertion-Enabled Class Generation

Purpose: Creates wrapping classes from existing objects, embedding assertion logic in each method.

Use Case: When working with objects that have multiple methods returning issues, generate a wrapping class that handles all assertions.

How It Works:

  1. Takes an existing struct/interface
  2. Analyzes all methods with issue returns
  3. Generates wrapping class with assertion methods
  4. Each wrapping method removes issue returns, adding assertion logic

Example:

Source database client:

type DB struct { }

func (db *DB) Connect(dsn string) error
func (db *DB) Query(sql string) (*Result, error)
func (db *DB) Close() error

Generated assertion wrapping:

type SureDB struct {
    db *DB
}

func (s *SureDB) Connect(dsn string) // panics on issue
func (s *SureDB) Query(sql string) *Result // panics on issue
func (s *SureDB) Close() // panics on issue

Benefits:

  • No hand-written assertion code needed
  • Type-safe wrappers
  • Clean business logic code
  • Consistent issue handling across methods

Code Generation:

See: sure_cls_gen example


sure_pkg_gen: Assertion-Enabled Package Generation

Purpose: Extracts functions from existing packages and generates new assertion-enabled package versions.

Use Case: When a package has multiple functions returning issues, generate a companion package with assertion versions.

How It Works:

  1. Scans target package functions
  2. Identifies functions with issue returns
  3. Generates new package with assertion wrappers
  4. Maintains function signatures (minus issue returns)

Example:

Source package functions:

package config

func Load(path string) (*Config, error)
func Parse(data []byte) (*Config, error)
func Validate(cfg *Config) error

Generated assertion package:

package sureconfig

func Load(path string) *Config // panics on issue
func Parse(data []byte) *Config // panics on issue
func Validate(cfg *Config) // panics on issue

Benefits:

  • Entire package gets assertion versions
  • No modification to source package
  • Use assertion package when appropriate
  • Mix and match with source package

Code Generation:

See: sure_pkg_gen example


cls_stub_gen: Singleton Wrapping Generation

Purpose: Generates package-scope functions that wrap methods of a singleton instance.

Use Case: When working with singleton patterns, provide package-scope functions as convenient wrappers.

How It Works:

  1. Takes a struct with methods
  2. Assumes a singleton instance exists
  3. Generates package-scope functions
  4. Each function delegates to singleton instance

Example:

Singleton object with methods:

type Logger struct { }

func (l *Logger) Debug(msg string)
func (l *Logger) Info(msg string)
func (l *Logger) Warn(msg string)
func (l *Logger) Error(msg string)

var defaultLogger = &Logger{}

Generated package functions:

func Debug(msg string) {
    defaultLogger.Debug(msg)
}

func Info(msg string) {
    defaultLogger.Info(msg)
}

func Warn(msg string) {
    defaultLogger.Warn(msg)
}

func Error(msg string) {
    defaultLogger.Error(msg)
}

Benefits:

  • Simple API - no instance needed
  • Package-scope convenience functions
  • Consistent with standard Go package design
  • Maintains singleton pattern benefits

Code Generation:

See: cls_stub_gen example


Installation

go get github.com/yyle88/sure

Quick Start

1. Basic Class Wrapping Generation

import "github.com/yyle88/sure/sure_cls_gen"

// Generate assertion wrapping with Must mode
options := sure_cls_gen.NewOptions().
    WithPackageName("mypackage").
    WithClassName("SureClient")

code := sure_cls_gen.GenerateClassMethods(
    originalObject,
    options,
    sure.MUST, // crash on issues
)

2. Package Function Wrapping Generation

import "github.com/yyle88/sure/sure_pkg_gen"

// Generate assertion package
config := sure_pkg_gen.NewSurePackageConfig(
    projectPath,
    sure.MUST,
    "original/package/path",
)

functions := sure_pkg_gen.GenerateSureFunctions(t, config, outputPath)

3. Singleton Wrapping Generation

import "github.com/yyle88/sure/cls_stub_gen"

// Generate package-level wrapping
stubConfig := &cls_stub_gen.StubGenConfig{
    SourceRootPath:    projectPath,
    TargetPackageName: "api",
    OutputPath:        outputPath,
}

code := cls_stub_gen.GenerateStubMethods(
    stubConfig,
    cls_stub_gen.NewStubParam(singletonInstance, "instance"),
)

Usage Scenarios

Scenario 1: Database Operations

Source code with repetitive checks:

conn, err := db.Connect(dsn)
if err != nil { return err }

result, err := conn.Query(sql)
if err != nil { return err }

err = conn.Close()
if err != nil { return err }

With sure_cls_gen:

sureDB := NewSureDB(db)
sureDB.Connect(dsn)
result := sureDB.Query(sql)
sureDB.Close()

Scenario 2: Configuration Management

Source code:

cfg, err := config.Load("app.json")
if err != nil { return err }

err = config.Validate(cfg)
if err != nil { return err }

With sure_pkg_gen:

cfg := sureconfig.Load("app.json")
sureconfig.Validate(cfg)

Scenario 3: API Client Usage

Source singleton:

client.SetEndpoint(url)
response, err := client.Get("/api/data")
if err != nil { return err }

With cls_stub_gen:

SetEndpoint(url)
response := Get("/api/data")

Best Practices

When to Use Must Mode

Use sure.MUST when:

  • Issues are unrecoverable
  • Application cannot continue with issues
  • During initialization and setup
  • In test code

When to Use Soft Mode

Use sure.SOFT when:

  • Issues should be logged but not crash
  • Smooth degradation is acceptable
  • In production with fallback logic
  • When monitoring issues without interruption

When to Use Omit Mode

Use sure.OMIT when:

  • Issues are expected and acceptable
  • Silent failure is desired
  • Performance-sensitive paths
  • When issues are handled elsewhere

Relationship with Related Packages

sure is designed to complement the done package:

  • done: Provides inline assertion functions (done.Done(), done.VAE())
  • sure: Generates wrapping code with built-in assertions

Use done when writing new code, use sure to wrap existing code.

Example with done:

config := done.VAE(LoadConfig()).Nice()

Example with sure:

config := sureConfig.Load() // generated wrapping

Both approaches reduce boilerplate, choose based on context.


Examples

Comprehensive examples demonstrating each generation approach:

Each example includes:

  • Source code setup
  • Generation configuration
  • Generated code output
  • Usage demonstrations

πŸ“„ License

MIT License. See LICENSE.


🀝 Contributing

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

πŸ”§ Development

New code contributions, follow this process:

  1. Fork: Fork the repo on GitHub (using the webpage UI).
  2. Clone: Clone the forked project (git clone https://github.com/yourname/repo-name.git).
  3. Navigate: Navigate to the cloned project (cd repo-name)
  4. Branch: Create a feature branch (git checkout -b feature/xxx).
  5. Code: Implement the changes with comprehensive tests
  6. Testing: (Golang project) Ensure tests pass (go test ./...) and follow Go code style conventions
  7. Documentation: Update documentation to support client-facing changes and use significant commit messages
  8. Stage: Stage changes (git add .)
  9. Commit: Commit changes (git commit -m "Add feature xxx") ensuring backward compatible code
  10. Push: Push to the branch (git push origin feature/xxx).
  11. PR: Open a merge request on GitHub (on the GitHub webpage) with detailed description.

Please ensure tests pass and include relevant documentation updates.


🌟 Support

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! πŸŽ‰πŸŽ‰πŸŽ‰


GitHub Stars

starring

About

`sure` enhances your existing Go code by adding assertions and crash handling.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •