Skip to content

apperia-de/goroutine

Repository files navigation

logo

goroutine

Go Report Card GitHub go.mod Go version GitHub

A goroutine wrapper for creating and running panic-safe goroutines and task groups.

The purpose of this package is to provide a simple wrapper function for goroutines which automatically handles panics. Starting a new goroutine without recovering from a possible panic inside it could crash the whole application.

The Go function runs an arbitrary function f in a separate goroutine, recovering from any panic and returning the outcome via a channel.

Installation

go get -u github.com/sknr/goroutine

Usage (with dot import)

Instead of running:

go func() {
    panic("Panic raised in goroutine")
}()

simply call:

Go(func() {
    panic("Panic raised in goroutine")
})

to create a panic-safe goroutine.

Functions with multiple input parameters must be wrapped within an anonymous function:

Go(func() {
    func(a, b int) {
        panic(a+b)
    }(21, 21)
})

Examples

package main

import (
    "fmt"
    "github.com/sknr/goroutine"
    "log"
)

func init() {
    // Override the default recover function.
    goroutine.SetDefaultRecoverFunc(func(v any, done chan<- error) {
        log.Printf("panic recovered: %v", v)
        done <- fmt.Errorf("panic in goroutine successfully recovered")
    })
}

func main() {
    for i := -3; i <= 3; i++ {
        err := <-goroutine.Go(func() {
            func(a, b int) {
                log.Println(a, "/", b, "=", a/b)
            }(10, i)
        })
        if err != nil {
            log.Println("error:", err)
        }
    }
}

Set a Custom Default Recover Function

To override the default recover function globally for new goroutines (created with Go(func()) or New(func())), pass a custom recover function of type RecoverFunc to SetDefaultRecoverFunc:

goroutine.SetDefaultRecoverFunc(func(v any, done chan<- error) {
    done <- fmt.Errorf("recovered: %v", v)
})

Create a Goroutine Instance with a Custom Recover Function

If you need different recover functions for different goroutines, use New and the fluent WithRecover method:

goroutine.New(func() {
    func(name string) {
        panic(fmt.Sprintln("Hallo", name))
    }("Welt")
}).WithRecover(func(v any, done chan<- error) {
    log.Printf("Custom recover: %v", v)
    done <- fmt.Errorf("custom recovery: %v", v)
}).Go()

Concurrent Group Execution (goGroup)

For coordinating groups of multiple panic-safe goroutines, use goGroup. It tracks tasks using a wait group and executes a registered error listener asynchronously when errors occur.

package main

import (
    "fmt"
    "github.com/sknr/goroutine"
    "log"
)

func main() {
    gg := goroutine.NewGoGroup()

    // Register a thread-safe listener for errors
    gg.ErrorListener(func(err error) {
        log.Println("Listener captured error:", err)
    })

    // Spawn concurrent safe tasks
    gg.Go(func() {
        log.Println("Running task 1...")
    })
    gg.Go(func() {
        panic("task 2 failed")
    })

    // Block until all tasks finish
    gg.Wait()
}

Inspecting Panic Errors

All panic errors returned by this library are wrapped in *goroutine.PanicError. This enables checking the recovered panic value and unwrapping inner errors.

Access the Original Panic Value

Type-assert the error to *goroutine.PanicError and call Value():

err := <-goroutine.Go(func() {
    panic("critical system error")
})

if err != nil {
    if panicErr, ok := err.(*goroutine.PanicError); ok {
        fmt.Println("Panic value:", panicErr.Value()) // Output: critical system error
    }
}

Standard Go Unwrapping

If the goroutine panics with a standard error object, PanicError implements Unwrap() error. This allows standard utilities like errors.Is or errors.As to function seamlessly:

targetErr := errors.New("connection failed")
err := <-goroutine.Go(func() {
    panic(targetErr)
})

if errors.Is(err, targetErr) {
    fmt.Println("Successfully matched unwrapped error!")
}

Logo

About

A goroutine wrapper for creating and running panic safe goroutines.

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Packages

 
 
 

Contributors