run

A drop-in replacement for oklog/run with automatic panic recovery.
Features
- Drop-in replacement: Compatible with
oklog/run.Group API
- Automatic panic recovery: All panics in actors are caught and converted to errors
- Custom panic handlers: Optional custom handling of panic situations
- Zero dependencies: Only depends on
oklog/run
- 100% test coverage: Thoroughly tested with comprehensive test suite
Installation
go get github.com/dio/run
Quick Start
package main
import (
"errors"
"fmt"
"log"
"github.com/dio/run"
)
func main() {
g := run.New()
// Add an actor that might panic
g.Add(func() error {
// This panic will be caught and converted to an error
panic("something went wrong")
}, func(err error) {
log.Printf("Actor interrupted: %v", err)
})
// Add a normal actor
g.Add(func() error {
return errors.New("normal error")
}, func(err error) {
log.Printf("Actor interrupted: %v", err)
})
if err := g.Run(); err != nil {
log.Printf("Group failed: %v", err)
}
}
Usage
Basic Usage
The run.Group works exactly like oklog/run.Group but with automatic panic recovery:
g := run.New()
g.Add(execute, interrupt)
err := g.Run()
Custom Panic Handler
You can provide a custom panic handler to process panics in your own way:
g := run.NewWithHandler(func(panicValue any, stackTrace string) error {
// Log the panic with custom formatting
log.Printf("PANIC: %v\nStack trace:\n%s", panicValue, stackTrace)
// Return a custom error
return fmt.Errorf("actor panicked: %v", panicValue)
})
Error Handling
When an actor panics, it's automatically converted to a PanicError:
err := g.Run()
if err != nil {
if panicErr, ok := err.(*run.PanicError); ok {
fmt.Printf("Actor panicked with value: %v\n", panicErr.Value)
fmt.Printf("Stack trace:\n%s\n", panicErr.StackTrace)
}
}
API Reference
Types
Group
type Group struct {
// PanicHandler is called when an actor panics.
// If nil, panics are converted to PanicError and returned.
PanicHandler func(panicValue any, stackTrace string) error
}
PanicError
type PanicError struct {
Value any // The panic value
StackTrace string // Stack trace at panic time
}
Functions
New
func New() *Group
Creates a new Group with panic recovery enabled.
NewWithHandler
func NewWithHandler(handler func(panicValue any, stackTrace string) error) *Group
Creates a new Group with a custom panic handler.
Methods
Add
func (g *Group) Add(execute func() error, interrupt func(error))
Add an actor to the group. This is a drop-in replacement for oklog/run.Group.Add().
Run
func (g *Group) Run() error
Execute all actors. This is identical to oklog/run.Group.Run().
Development
Prerequisites
- Go 1.24+
- golangci-lint (installed via
go tool)
Building
go build ./...
Testing
go test -v -race -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
Linting
go tool golangci-lint run
go tool golangci-lint fmt
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature)
- Make your changes
- Add tests for your changes
- Ensure all tests pass (
go test ./...)
- Run linting (
go tool golangci-lint run)
- Commit your changes (
git commit -am 'Add amazing feature')
- Push to the branch (
git push origin feature/amazing-feature)
- Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
- oklog/run - The original actor model implementation
- Inspired by the need for safer concurrent programming in Go