The full startup example can panic on dependency failure and discards server startup errors
Source references: 5The guide states that `MustInvoke` panics on error, yet the complete `main` example uses it at the composition root, where no enclosing `Invoke` converts that panic back to an error. It also calls `ListenAndServe` in a goroutine and ignores its return value.
A provider initialization failure can terminate the process. A bind or listener failure can instead leave a process waiting for a signal while serving no HTTP traffic, harming availability and failure detection.
The guide says `MustInvoke` panics on failure and is safe inside providers when an enclosing `Invoke` converts that panic to an error. The full `main` example instead calls it directly at the composition root, so initialization failure can terminate the process. It also discards `ListenAndServe`'s error in a goroutine; on a bind/listen failure, the process may remain waiting for shutdown while serving nothing. Users can request explicit handling of resolution and server-start errors.
// (e.g. an HTTP handler that must degrade gracefully instead of crashing)db, err := do.Invoke[Database](injector)// MustInvoke panics on error — preferred in providers, recovered by do.Invoke on the parent calldb := do.MustInvoke[Database](injector)```Show 4 other places
server := do.MustInvoke[*http.Server](injector) go server.ListenAndServe() _ = injector.ShutdownOnSignalsWithContext(context.Background(), os.Interrupt)}| -------------------------- | ----------------------------------------- || `do.Invoke[T]()` | Get service (with error) || `do.InvokeNamed[T]()` | Get named service || `do.InvokeAs[T]()` | Get first service matching interface || `do.InvokeStruct[T]()` | Inject into struct fields using tags || `do.MustInvoke[T]()` | Get service (panic on error) || `do.MustInvokeNamed[T]()` | Get named service (panic on error) |```go// Invoke with error handling — reserve for call sites outside the DI graph// (e.g. an HTTP handler that must degrade gracefully instead of crashing)db, err := do.Invoke[Database](injector)// MustInvoke panics on error — preferred in providers, recovered by do.Invoke on the parent calldb := do.MustInvoke[Database](injector)```Inside a provider function, always use `do.MustInvoke` (or `MustInvokeAs`/`MustInvokeNamed`/`MustInvokeStruct`) rather than the error-returning variant:- A provider already returns `(T, error)`, so propagating a dependency failure with `do.Invoke` costs an extra `if err != nil { return nil, err }` on every call.- `do.MustInvoke` panics instead, but samber/do correctly catches and recovers that panic at the enclosing `Invoke` call and converts it back into a regular error — this recover happens inside the library itself, not in caller code, so `MustInvoke` is safe to use inside providers.- The failure still surfaces as an error at the composition root, just without the manual boilerplate in every provider.## Full Application Setup```gofunc main() { injector := do.New( infrastructure.Package, repository.Package, service.Package, transport.Package, ) server := do.MustInvoke[*http.Server](injector) go server.ListenAndServe() _ = injector.ShutdownOnSignalsWithContext(context.Background(), os.Interrupt)}```