zoobzio January 24, 2026 Edit this page

Quickstart

Install slush and register your first guarded service.

Installation

go get github.com/zoobzio/slush

Requires Go 1.24 or later.

Basic Usage

package main

import (
    "context"
    "errors"
    "fmt"

    "github.com/zoobzio/slush"
)

// Define a service contract
type Greeter interface {
    Greet(name string) string
}

// Implement it
type englishGreeter struct{}

func (g englishGreeter) Greet(name string) string {
    return fmt.Sprintf("Hello, %s!", name)
}

func main() {
    // Initialize the registry (once per process)
    key := slush.Start()

    // Register the service with a guard
    slush.Register[Greeter](key, englishGreeter{}).
        Guard(func(ctx context.Context) error {
            // Your access logic here
            return nil
        })

    // Retrieve it
    ctx := context.Background()
    greeter, err := slush.Use[Greeter](ctx)
    if err != nil {
        panic(err)
    }

    fmt.Println(greeter.Greet("World"))
    // Output: Hello, World!
}

Registering Services

First, initialize the registry with Start(). This returns a Key that authorizes registration.

key := slush.Start()  // Call once at startup

Register services by interface type. The implementation is stored; the interface type is the lookup key.

slush.Register[Database](key, postgresDB)
slush.Register[Mailer](key, sendgridMailer)
slush.Register[Logger](key, zapLogger)

You own the service lifecycle. Create and initialize services before registering; slush just stores and retrieves them.

Optionally, freeze the registry to prevent further registration:

slush.Freeze(key)  // No more registrations allowed

Adding Guards

Guards are functions that validate context before service access. Chain them with .Guard():

slush.Register[Database](key, db).
    Guard(requireAuth).
    Guard(requireRole("admin")).
    Guard(rateLimit(100))

Guards run in order. The first error stops the chain and returns ErrAccessDenied.

See Guards Guide for composition patterns.

Retrieving Services

Use Use[T](ctx) to retrieve a service:

db, err := slush.Use[Database](ctx)
if errors.Is(err, slush.ErrNotFound) {
    // Service not registered
}
if errors.Is(err, slush.ErrAccessDenied) {
    // Guard rejected the request
}

For bootstrap code where errors should panic, use MustUse:

logger := slush.MustUse[Logger](ctx)

Next Steps