Quick Start
Create a container, register services, and resolve dependencies
Installation
go get github.com/xraph/vesselMinimal 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
- Constructors --
In/Outstructs, named instances, groups - Lifetimes and Scopes -- singleton, transient, scoped
- Forge Integration -- using Vessel inside a Forge application
How is this guide?