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
- Concepts — Understand services, guards, and handles
- Architecture — How slush works internally
- Testing Guide — Test code that uses slush