Forge
1.x
Docs/Forge/Quick Start
Open

Reading3 min
Updated31 Jul 2026
Sourcev1/vessel/quick-start.mdx

Installation01

go get github.com/xraph/vessel

Minimal Setup02

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 Pattern03

  • 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 Registration04

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 Steps05