Your First Container
A container holds your application’s services. You register services with a collection, then build it into a provider that creates instances on demand.
The Pattern
Collection (registration) → Build → Provider (resolution)
Step 1: Create a Collection
services := godi.NewCollection()
The collection is where you tell godi about your services.
Step 2: Register a Service
services.AddSingleton(func() string {
return "Hello, godi!"
})
This registers a string service. The function is called when the service is first needed.
Step 3: Build the Provider
provider, err := services.Build()
if err != nil {
log.Fatal(err)
}
defer provider.Close()
Building validates your registrations and prepares the dependency graph. Always close the provider when done - it cleans up resources.
Step 4: Resolve the Service
message := godi.MustResolve[string](provider)
fmt.Println(message) // Hello, godi!
MustResolve returns the service or panics. Use Resolve if you want to handle errors yourself.
Complete Example
package main
import (
"fmt"
"log"
"github.com/junioryono/godi/v4"
)
func main() {
// 1. Create collection
services := godi.NewCollection()
// 2. Register service
services.AddSingleton(func() string {
return "Hello, godi!"
})
// 3. Build provider
provider, err := services.Build()
if err != nil {
log.Fatal(err)
}
defer provider.Close()
// 4. Use service
message := godi.MustResolve[string](provider)
fmt.Println(message)
}
What Just Happened?
┌─────────────────────────────────────────────────────┐
│ Collection │
│ ┌─────────────────────────────────────────────┐ │
│ │ string → func() string { return "Hello" } │ │
│ └─────────────────────────────────────────────┘ │
└────────────────────────┬────────────────────────────┘
│ Build()
▼
┌─────────────────────────────────────────────────────┐
│ Provider │
│ ┌─────────────────────────────────────────────┐ │
│ │ MustResolve[string]() → "Hello, godi!" │ │
│ └─────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
You registered a
stringservice with a factory functionBuilding created the provider with the dependency graph
Resolving called your factory and returned the result
Key Points
Collection is for registration (before the app runs)
Provider is for resolution (while the app runs)
Build validates everything upfront - no runtime surprises
Close cleans up resources when you’re done