-
Notifications
You must be signed in to change notification settings - Fork 216
Description
Take the following minimal example:
package main
import (
"fmt"
"go.uber.org/dig"
)
type A struct {
b *B
c *C
}
type B struct{}
type C struct{}
type D struct{}
type paramsA struct {
dig.In
B *B
C *C `optional:"true"`
}
func main() {
c := dig.New()
c.Provide(func(p paramsA) *A {
return &A{
b: p.B,
c: p.C,
}
})
c.Provide(func() *B { return &B{} })
c.Provide(func(d *D) *C { return &C{} })
if err := c.Invoke(func(a *A) {
fmt.Printf("a.c == nil is %t \n", a.c == nil)
}); err != nil {
panic(err)
}
}
Running this will return the string "a.c == nil is true"
. Despite the fact that a constructor was Provide
d to the container for *C
, there is no feedback to the user that a.c == nil
because *C
's dependencies were not fulfilled. The only way to arrive at this conclusion without tracing back every optional dependency to all of their dependencies is to remove the optional:"true"
tag temporarily and see what error dig returns when the container is resolved.
Instead, I contend that when an optional dependency does have a constructor Provide
d to the container, either (1) an error should always be returned if the optional dependency's dependencies cannot be met, or (2) a flag should able to be provided to the container (maybe some "strict" mode?) for cause optional dependency errors to be returned for easy debuggability.