act

package module
v0.11.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 23, 2026 License: MIT Imports: 8 Imported by: 11

README

act

A Go library for assertion, error handling, and resource management utilities.

Installation

go get go.xrfang.cn/act

Classic Usage Patterns

Example 1: Basic Error Handling
func sendFile(filename string, conn net.Conn) (n int, err error) {
    defer act.Catch(&err)
    f, err := os.Open(filename)
    act.Assert(err)
    defer f.Close()
    act.Ensure(io.Copy(conn, f)).Scan(&n) 
    return
}

func main() {
    act.SetLogWriter(logger)
    sendFile("file.txt", conn)
}

Best Practices:

  • Use defer act.Catch(&err) at the beginning of functions to capture errors. Handle all errors with panic instead of if err != nil to reduce conditional logic and make the function flow clearer.
  • act.Catch preserves original, unwrapped errors (e.g., SQL errors) for easy checking by callers, while automatically logging stack traces for debugging.
  • Prefer act.Assert(err) over act.Assert(err == nil, "error occurred: %w", err). Use stack traces as the primary debugging tool rather than wrapping error messages, which makes it harder to access original error objects.
  • Use act.Ensure appropriately to make code more concise.
Example 2: Complex Error Handling with Callbacks
func saveData(w io.Writer, r io.Reader) {
    act.Ensure(io.Copy(w, r))
}

func fetchData(conn net.Conn, saveAs string) (err error) {
    f, err := os.Create(saveAs)
    if err != nil {
        return err
    }
    defer act.Catch(func(e error) error {
        e = act.FirstError(e, f.Close())
        if os.IsNotExist(e) {
            err = nil
            return nil
        }
        return e
    })
    saveData(f, conn)
    return
}

Best Practices:

  • Handle complex logic in act.Catch callbacks. This example shows:
    • How to collect multiple errors and return the first one (earlier errors are more important)
    • Flexibly ignore certain errors by not setting the return value
    • The difference between setting the return value (for callers) and callback return value (for act's logging). If the callback returns nil, act considers no error occurred and won't log.
  • Internal functions should avoid returning errors and instead use panic to pass errors to callers. Returning errors breaks the call stack, making debugging difficult.

Documentation

Overview

Package act provides a collection of utilities for assertion, error handling, and resource management in Go applications. It focuses on making common patterns more concise and expressive.

Main Features:

  • Assertion utilities with customizable error messages
  • Panic recovery and error handling with deferred cleanup
  • Value validation and extraction utilities
  • Stack trace collection and logging
  • Error coalescing for resource cleanup scenarios

The package is designed to be used in scenarios where you want to reduce boilerplate code in error handling and assertion patterns, particularly in functions with complex resource management requirements.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Assert

func Assert(e any, ntfy ...any)

Assert checks the given value and panics if the assertion fails. The behavior depends on the type of the value:

  • nil: No assertion, always passes
  • bool: Panics if the value is false
  • error: Panics if the error is not nil
  • other types: Panics with a type error

Optional notification parameters can be provided to customize the panic message:

  • If no parameters provided: Uses default message
  • If one parameter: Used as a format string
  • If multiple parameters: First is format string, rest are format arguments

Example:

act.Assert(result != nil, "result cannot be nil")
act.Assert(err, "operation failed: %s", operation)

func Catch

func Catch(h any)

Catch recovers from panics and handles them according to the provided handler. It supports three types of handlers:

  1. nil: Only logs the panic (if logging is enabled)
  2. *error: Assigns the panic (converted to error) to the pointed error variable
  3. func(error) error: Calls the function with the panic error and uses the returned error for logging

The function is designed to be used in defer statements for panic recovery and error handling in complex functions.

Example:

func example() (err error) {
    defer act.Catch(&err)
    // risky code here
    return nil
}

func exampleWithCleanup() (err error) {
    defer act.Catch(func(e error) error {
        // cleanup resources
        return act.FirstError(e, f.Close())
    })
    // risky code here
    return nil
}

func FirstError added in v0.9.0

func FirstError(errs ...error) error

FirstError returns the first non-nil error from the provided errors. If all errors are nil or no errors are provided, it returns nil.

This function is particularly useful in defer blocks for resource cleanup, where you want to preserve the first error that occurred while still attempting to clean up all resources.

Example:

defer func() {
    err = act.FirstError(err, f.Close(), conn.Close(), cleanup())
    return err
}()

func Log added in v0.2.0

func Log(msg string, args ...any)

Log writes a formatted message to the configured log writer. If no log writer is configured, the message is discarded. The message is automatically suffixed with a newline if not already present.

Example:

act.Log("operation completed successfully")
act.Log("error occurred: %v", err)

func SetConsoleErrorLevel added in v0.6.0

func SetConsoleErrorLevel(level byte)

SetConsoleErrorLevel sets the error level for console output (stderr/stdout). Valid levels are 0-2, where higher levels include more detail:

  • 0: No error logging
  • 1: Error message only
  • 2: Error message with stack trace

Values greater than 2 are clamped to 2.

Example:

act.SetConsoleErrorLevel(2) // full stack traces

func SetLogWriter

func SetLogWriter(w io.Writer)

SetLogWriter configures the destination for log messages. The writer affects the error logging level:

  • nil: Disables all logging (effective error level = 0)
  • os.Stderr/os.Stdout: Uses console error level
  • Other writers: Always logs with full stack traces (level = 2)

Example:

act.SetLogWriter(os.Stdout)
act.SetLogWriter(nil) // disable logging

func Trace

func Trace() []string

Trace returns a formatted stack trace, skipping runtime and act package frames. Each entry in the returned slice has the format: "(file:line) function".

This is useful for debugging and error reporting when you need to show the call stack that led to a particular point in the code.

Example:

for _, line := range act.Trace() {
    fmt.Println(line)
}

func Wrap added in v0.10.0

func Wrap(err error) error

Types

type Error added in v0.10.0

type Error struct {
	// contains filtered or unexported fields
}

func (Error) Error added in v0.10.0

func (e Error) Error() string

func (Error) Raw added in v0.10.0

func (e Error) Raw() error

func (Error) Trace added in v0.10.0

func (e Error) Trace() []string

type Vals added in v0.4.0

type Vals []any

Vals represents a slice of interface{} values with scanning capabilities.

func Ensure added in v0.7.0

func Ensure(vs ...any) Vals

Ensure validates the last value and returns the preceding values. The last value must be either a bool (must be true) or an error (must be nil). If the validation fails, the function panics.

This is useful for validating function results and extracting values in a single expression.

Example:

n, err := io.Copy(dst, src)
size := act.Ensure(n, err == nil)[0].(int64)

func (Vals) Get added in v0.11.0

func (v Vals) Get[T any](idx int) T

Get returns the value at idx, type-asserted to T. It panics if the type assertion fails. Complements Scan for typed extraction without reflection. Requires Go 1.27+ for generic methods.

Example:

n, _ := io.Copy(dst, src)
size := act.Ensure(n, true).Get[int64](0)

func (Vals) Scan added in v0.4.0

func (vs Vals) Scan(ps ...any)

Scan copies values from this Vals slice to the provided pointers. All pointers must be non-nil and the number of pointers must match the number of values. Type conversion is performed when possible.

Panics if:

  • Number of pointers doesn't match number of values
  • Any pointer is nil
  • Type conversion fails

Example:

vals := act.Ensure(val1, val2, condition)
var i int
var s string
vals.Scan(&i, &s)

Source Files

  • assert.go
  • catch.go
  • ensure.go
  • error.go
  • logging.go
  • trace.go
  • utils.go

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL