Quick Start

Create a container, register services, and resolve dependencies

Installation

go get github.com/xraph/vessel

Minimal Setup

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/xraph/vessel"
)

type Database struct {
    DSN string
}

func (d *Database) Name() string              { return "database" }
func (d *Database) Start(ctx context.Context) error { fmt.Println("DB connected"); return nil }
func (d *Database) Stop(ctx context.Context) error  { fmt.Println("DB disconnected"); return nil }

type UserService struct {
    db *Database
}

func main() {
    c := vessel.New()

    // Register constructors -- dependencies resolved by Go type
    vessel.Provide(c, func() *Database {
        return &Database{DSN: "postgres://localhost:5432/app"}
    })

    vessel.Provide(c, func(db *Database) *UserService {
        return &UserService{db: db}
    })

    // Resolve by type
    userService, err := vessel.Inject[*UserService](c)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("UserService uses DB at %s\n", userService.db.DSN)

    // Start all services (respects dependency order)
    ctx := context.Background()
    if err := c.Start(ctx); err != nil {
        log.Fatal(err)
    }
    defer c.Stop(ctx)
}

Why This Pattern

  • Dependencies are resolved by Go type, not string keys.
  • Constructors are plain functions -- easy to test and reason about.
  • Registration stays close to actual object construction.
  • Refactors are safer because types are checked at compile time.
  • The container starts and stops services in topological order.

Alternative: Named Registration

When you need explicit names (for multiple instances of the same type, or compatibility with existing code), use ProvideNamed:

c := vessel.New()

vessel.ProvideNamed(c, "database", func() (*Database, error) {
    return &Database{DSN: "postgres://localhost:5432/app"}, nil
}, vessel.AsSingleton())

db, err := vessel.InjectNamed[*Database](c, "database")

You can also register a pre-built value:

cfg := &AppConfig{Port: 8080}
vessel.ProvideValue(c, cfg, vessel.WithName("config"))

config, err := vessel.InjectNamed[*AppConfig](c, "config")

Next Steps

How is this guide?

On this page