Documentation ¶
Overview ¶
Example (HighLevelAPI) ¶
package main import ( "fmt" "github.com/rectcircle/digpro" "go.uber.org/dig" ) func main() { // High Level API has better error output type Foo struct { A string B int C int `name:"c"` private bool //lint:ignore U1000 for test ignore int `digpro:"ignore"` } // new a *dig.Container wrapper - *digpro.ContainerWrapper c := digpro.New() // provide some constructor digpro.QuickPanic( // register object c.Supply("a"), c.Supply(1), c.Supply(2, dig.Name("c")), c.Supply(true), c.Supply("aaa", digpro.Override()), // Override "a" by "aaa" // register a struct c.Struct(Foo{ ignore: 3, }), ) // extract object from container foo, err := c.Extract(Foo{}) if err != nil { digpro.QuickPanic(err) } fmt.Printf("%#v", foo) }
Output: digpro_test.Foo{A:"aaa", B:1, C:2, private:true, ignore:3}
Example (LowerLevelAPI) ¶
package main import ( "fmt" "github.com/rectcircle/digpro" "go.uber.org/dig" ) func main() { // Lower Level API can be used quickly, but the error is not friendly enough, such as: // ... missing dependencies for function "reflect".makeFuncStub (/usr/local/Cellar/go/1.17.1/libexec/src/reflect/asm_amd64.s:30) ... type Foo struct { A string B int C int `name:"c"` private bool //lint:ignore U1000 for test ignore int `digpro:"ignore"` } // new a *dig.Container c := dig.New() // provide some constructor digpro.QuickPanic( // register object c.Provide(digpro.Supply("a")), c.Provide(digpro.Supply(1)), c.Provide(digpro.Supply(true)), c.Provide(digpro.Supply(2), dig.Name("c")), // register a struct c.Provide(digpro.Struct(Foo{ ignore: 3, })), ) // extract object from container foo, err := digpro.Extract(c, Foo{}) if err != nil { digpro.QuickPanic(err) } fmt.Printf("%#v", foo) }
Output: digpro_test.Foo{A:"a", B:1, C:2, private:true, ignore:3}
Index ¶
- func Extract(c *dig.Container, typ interface{}, opts ...ExtractOption) (interface{}, error)
- func MakeExtractFunc(ptr interface{}, opts ...ExtractOption) interface{}
- func Override() dig.ProvideOption
- func QuickPanic(errs ...error)
- func ResolveCyclic() dig.ProvideOption
- func Struct(structOrStructPtr interface{}) interface{}
- func Supply(value interface{}) interface{}
- type ContainerWrapper
- func (c *ContainerWrapper) Extract(typ interface{}, opts ...ExtractOption) (interface{}, error)
- func (c *ContainerWrapper) Invoke(function interface{}, opts ...dig.InvokeOption) error
- func (c *ContainerWrapper) Provide(constructor interface{}, opts ...dig.ProvideOption) error
- func (c *ContainerWrapper) Struct(structOrStructPtr interface{}, opts ...dig.ProvideOption) error
- func (c *ContainerWrapper) Supply(value interface{}, opts ...dig.ProvideOption) error
- func (c *ContainerWrapper) Unwrap() *dig.Container
- func (c *ContainerWrapper) Visualize(w io.Writer, opts ...dig.VisualizeOption) error
- type ExtractOption
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Extract ¶
func Extract(c *dig.Container, typ interface{}, opts ...ExtractOption) (interface{}, error)
Extract a value from dig.Container by type of value.
if want to extract a non-interface, reflect.TypeOf(result) == reflect.TypeOf(typ). look like
func(int) -> int // func(int(0)) -> int func(*int) -> *int // func(new(int)) -> *int
if want to extract a interface, reflect.TypeOf(result) == reflect.TypeOf(typ).Elem(). look like
type A interface { ... } func(A) -> error // func(A(nil)) -> error func(*A) -> A // func(new(A)) -> A func(**A) -> *A // func(new(*A)) -> *A
for example
c := dig.New() _ = c.Provide(func() int {return 1}) // please handle error in production i, _ := digpro.Extract(c, int(0)) fmt.Println(i.(int) == 1) // Output: true
Example ¶
package main import ( "fmt" "github.com/rectcircle/digpro" "go.uber.org/dig" ) func main() { c := dig.New() _ = c.Provide(func() int { return 1 }) // please handle error in production i, _ := digpro.Extract(c, int(0)) fmt.Println(i.(int) == 1) }
Output: true
func MakeExtractFunc ¶ added in v1.1.0
func MakeExtractFunc(ptr interface{}, opts ...ExtractOption) interface{}
MakeExtractFunc make Invoke function to extract a value and assign to *ptr from dig.Container, for example
c := dig.New() _ = c.Provide(func() int { return 1 }) // please handle error in production i := new(int) _ = c.Invoke(digpro.MakeExtractFunc(i)) fmt.Println(*i == 1) // Output: true
Example ¶
package main import ( "fmt" "github.com/rectcircle/digpro" "go.uber.org/dig" ) func main() { c := dig.New() _ = c.Provide(func() int { return 1 }) // please handle error in production i := new(int) _ = c.Invoke(digpro.MakeExtractFunc(i)) fmt.Println(*i == 1) }
Output: true
func Override ¶ added in v1.1.0
func Override() dig.ProvideOption
Override a registered provider and only support digpro high level api (support *digpro.ContainerWrapper and digglobal). if Container not exist provider, the option will return error: no provider to override was found. for example
c := digpro.New() _ = c.Supply(1) // please handle error in production _ = c.Supply(1, digpro.Override()) // _ = c.Supply("a", digpro.Override()) // has error i, _ := c.Extract(0) fmt.Println(i.(int) == 1) // Output: true
Example ¶
package main import ( "fmt" "github.com/rectcircle/digpro" ) func main() { c := digpro.New() _ = c.Supply(1) // please handle error in production _ = c.Supply(1, digpro.Override()) // _ = c.Supply("a", digpro.Override()) // has error i, _ := c.Extract(0) fmt.Println(i.(int) == 1) }
Output: true
func QuickPanic ¶
func QuickPanic(errs ...error)
QuickPanic if anyone of errs is not nil, will panic. for example
c := digpro.New() digpro.QuickPanic( c.Supply(1), c.Supply(1), ) // panic: [1]: cannot provide function "xxx".Xxx (xxx.go:n): cannot provide int from [0]: already provided by "xxx".Xxx (xxx.go:m)
func ResolveCyclic ¶ added in v1.2.0
func ResolveCyclic() dig.ProvideOption
ResolveCyclic to resolve *digpro.ContainerWrapper.Struct cyclic dependency. The option only support *digpro.ContainerWrapper.Struct and *digglobal.Struct functions.
for example
type D1 struct { D2 *D2 Value int } func (d1 *D1) String() string { return fmt.Sprintf("D1: {D2: {D1: ..., Value: '%s'}, Value: %d}", d1.D2.Value, d1.Value) } type D2 struct { D1 *D1 Value string } func (d2 *D2) String() string { return fmt.Sprintf("D2: {D1: {D2: ..., Value: %d}, Value: '%s'}", d2.D1.Value, d2.Value) } c := digpro.New() _ = c.Supply(1) // please handle error in production _ = c.Supply("a") _ = c.Struct(new(D1), digpro.ResolveCyclic()) // enable resolve cyclic dependency _ = c.Struct(new(D2)) d1, _ := c.Extract(new(D1)) d2, _ := c.Extract(new(D2)) fmt.Println(d1.(*D1).String()) fmt.Println(d2.(*D2).String()) // Output: // D1: {D2: {D1: ..., Value: 'a'}, Value: 1} // D2: {D1: {D2: ..., Value: 1}, Value: 'a'} // Output: true
Example ¶
package main import ( "fmt" "github.com/rectcircle/digpro" "go.uber.org/dig" ) type D1 struct { D2 *D2 Value int } func (d1 *D1) String() string { return fmt.Sprintf("D1: {D2: {D1: ..., Value: '%s'}, Value: %d}", d1.D2.Value, d1.Value) } type D2 struct { D1 *D1 Value string } func (d2 *D2) String() string { return fmt.Sprintf("D2: {D1: {D2: ..., Value: %d}, Value: '%s'}", d2.D1.Value, d2.Value) } func resolvePointerTypeCyclicDependency() { c := digpro.New() _ = c.Supply(1) // please handle error in production _ = c.Supply("a") _ = c.Struct(new(D1), digpro.ResolveCyclic()) // enable resolve cyclic dependency _ = c.Struct(new(D2)) d1, _ := c.Extract(new(D1)) d2, _ := c.Extract(new(D2)) fmt.Println(d1.(*D1).String()) fmt.Println(d2.(*D2).String()) } type I1 interface{ String1() string } type I2 interface{ String2() string } type DI1 struct { I2 I2 Value int } func (d1 *DI1) String1() string { return fmt.Sprintf("DI1: {I2: {I1: ..., Value: '%s'}, Value: %d}", d1.I2.(*DI2).Value, d1.Value) } type DI2 struct { I1 I1 Value string } func (d2 *DI2) String2() string { return fmt.Sprintf("DI2: {I1: {I2: ..., Value: %d}, Value: '%s'}", d2.I1.(*DI1).Value, d2.Value) } func resolveInterfaceTypeCyclicDependency() { c := digpro.New() _ = c.Supply(1) // please handle error in production _ = c.Supply("a") _ = c.Struct(new(DI1), dig.As(new(I1))) _ = c.Struct(new(DI2), dig.As(new(I2)), digpro.ResolveCyclic()) // enable resolve cyclic dependency i1, _ := c.Extract(new(I1)) i2, _ := c.Extract(new(I2)) fmt.Println(i1.(I1).String1()) fmt.Println(i2.(I2).String2()) } func main() { resolvePointerTypeCyclicDependency() resolveInterfaceTypeCyclicDependency() }
Output: D1: {D2: {D1: ..., Value: 'a'}, Value: 1} D2: {D1: {D2: ..., Value: 1}, Value: 'a'} DI1: {I2: {I1: ..., Value: 'a'}, Value: 1} DI2: {I1: {I2: ..., Value: 1}, Value: 'a'}
func Struct ¶
func Struct(structOrStructPtr interface{}) interface{}
Struct make a struct constructor.
support all dig tags and `digpro:"ignore"`
struct { A string `name:"a"` B []string `group:"b"` C bool `optional:"true"` D string `digpro:"ignore"` // ignore this field }
for example
type Foo struct { A string B int C int `name:"c"` private bool ignore int `digpro:"ignore"` } // new a *dig.Container c := dig.New() // provide some constructor digpro.QuickPanic( // register object c.Provide(digpro.Supply("a")), c.Provide(digpro.Supply(1)), c.Provide(digpro.Supply(true)), c.Provide(digpro.Supply(2), dig.Name("c")), // register a struct c.Provide(digpro.Struct(Foo{ ignore: 3, })), // equals to // c.Provide(func(in struct { // A string // B int // C int `name:"c"` // Private bool // }) Foo { // return Foo{ // A: in.A, // B: in.B, // C: in.C, // private: in.Private, // ignore: 3, // } // }), ) // extract object from container foo, err := digpro.Extract(c, Foo{}) if err != nil { digpro.QuickPanic(err) } fmt.Printf("%#v", foo) // Output: digpro_test.Foo{A:"a", B:1, C:2, private:true, ignore:3}
Example ¶
package main import ( "fmt" "github.com/rectcircle/digpro" "go.uber.org/dig" ) func main() { type Foo struct { A string B int C int `name:"c"` private bool //lint:ignore U1000 for test ignore int `digpro:"ignore"` } // new a *dig.Container c := dig.New() // provide some constructor digpro.QuickPanic( // register object c.Provide(digpro.Supply("a")), c.Provide(digpro.Supply(1)), c.Provide(digpro.Supply(true)), c.Provide(digpro.Supply(2), dig.Name("c")), // register a struct c.Provide(digpro.Struct(Foo{ ignore: 3, })), // equals to // c.Provide(func(in struct { // A string // B int // C int `name:"c"` // Private bool // }) Foo { // return Foo{ // A: in.A, // B: in.B, // C: in.C, // private: in.Private, // ignore: 3, // } // }), ) // extract object from container foo, err := digpro.Extract(c, Foo{}) if err != nil { digpro.QuickPanic(err) } fmt.Printf("%#v", foo) }
Output: digpro_test.Foo{A:"a", B:1, C:2, private:true, ignore:3}
func Supply ¶
func Supply(value interface{}) interface{}
Supply a value into container. for example
c := dig.New() digpro.QuickPanic( // register object c.Provide(digpro.Supply("a")), // equals to // c.Provide(func() string {return "a"}), ) foo, err := digpro.Extract(c, string("")) if err != nil { digpro.QuickPanic(err) } fmt.Println(foo) // Output: a
Example ¶
package main import ( "fmt" "github.com/rectcircle/digpro" "go.uber.org/dig" ) func main() { c := dig.New() digpro.QuickPanic( // register object c.Provide(digpro.Supply("a")), // equals to // c.Provide(func() string {return "a"}), ) foo, err := digpro.Extract(c, string("")) if err != nil { digpro.QuickPanic(err) } fmt.Println(foo) }
Output: a
Types ¶
type ContainerWrapper ¶
ContainerWrapper is a dig.Container wrapper, for add some method
func New ¶
func New(opts ...dig.Option) *ContainerWrapper
New constructs a dig.Container wrapper and export some metholds.
For example.
c = digpro.New // dig.Container methold c.Provide(...) c.Invoke(...) // digpro exported methold c.Value(...) c.Struct(...)
func (*ContainerWrapper) Extract ¶
func (c *ContainerWrapper) Extract(typ interface{}, opts ...ExtractOption) (interface{}, error)
Extract a value from dig.Container by type of value.
if want to extract a non-interface, reflect.TypeOf(result) == reflect.TypeOf(typ). look like
func(int) -> int // func(int(0)) -> int func(*int) -> *int // func(new(int)) -> *int
if want to extract a interface, reflect.TypeOf(result) == reflect.TypeOf(typ).Elem(). look like
type A interface { ... } func(A) -> error // func(A(nil)) -> error func(*A) -> A // func(new(A)) -> A func(**A) -> *A // func(new(*A)) -> *A
for example
c := digpro.New() _ = c.Supply(1) // please handle error in production i, _ := c.Extract(int(0)) fmt.Println(i.(int) == 1) // Output: true
Example ¶
package main import ( "fmt" "github.com/rectcircle/digpro" ) func main() { c := digpro.New() _ = c.Supply(1) // please handle error in production i, _ := c.Extract(int(0)) fmt.Println(i.(int) == 1) }
Output: true
func (*ContainerWrapper) Invoke ¶ added in v1.2.0
func (c *ContainerWrapper) Invoke(function interface{}, opts ...dig.InvokeOption) error
func (*ContainerWrapper) Provide ¶ added in v1.1.0
func (c *ContainerWrapper) Provide(constructor interface{}, opts ...dig.ProvideOption) error
Provide teaches the container how to build values of one or more types and expresses their dependencies. more see: https://pkg.go.dev/go.uber.org/dig#Container.Provide.
digpro.ContainerWrapper.Provide() support digpro.Override() options, but dig.Container.Provide() not support
func (*ContainerWrapper) Struct ¶
func (c *ContainerWrapper) Struct(structOrStructPtr interface{}, opts ...dig.ProvideOption) error
Struct make a struct constructor.
support all dig tags and `digpro:"ignore"`
struct { A string `name:"a"` B []string `group:"b"` C bool `optional:"true"` D string `digpro:"ignore"` // ignore this field }
for example
type Foo struct { A string B int C int `name:"c"` private bool ignore int `digpro:"ignore"` } // new a *dig.Container c := digpro.New() // provide some constructor digpro.QuickPanic( // register object c.Supply("a"), c.Supply(1), c.Supply(true), c.Supply(2, dig.Name("c")), // register a struct c.Struct(Foo{ ignore: 3, }), // equals to // c.Provide(func(in struct { // A string // B int // C int `name:"c"` // Private bool // }) Foo { // return Foo{ // A: in.A, // B: in.B, // C: in.C, // private: in.Private, // ignore: 3, // } // }), ) // extract object from container foo, err := c.Extract(Foo{}) if err != nil { digpro.QuickPanic(err) } fmt.Printf("%#v", foo) // Output: digpro_test.Foo{A:"a", B:1, C:2, private:true, ignore:3}
Example ¶
package main import ( "fmt" "github.com/rectcircle/digpro" "go.uber.org/dig" ) func main() { type Foo struct { A string B int C int `name:"c"` private bool //lint:ignore U1000 for test ignore int `digpro:"ignore"` } // new a *dig.Container c := digpro.New() // provide some constructor digpro.QuickPanic( // register object c.Supply("a"), c.Supply(1), c.Supply(true), c.Supply(2, dig.Name("c")), // register a struct c.Struct(Foo{ ignore: 3, }), // equals to // c.Provide(func(in struct { // A string // B int // C int `name:"c"` // Private bool // }) Foo { // return Foo{ // A: in.A, // B: in.B, // C: in.C, // private: in.Private, // ignore: 3, // } // }), ) // extract object from container foo, err := c.Extract(Foo{}) if err != nil { digpro.QuickPanic(err) } fmt.Printf("%#v", foo) }
Output: digpro_test.Foo{A:"a", B:1, C:2, private:true, ignore:3}
func (*ContainerWrapper) Supply ¶
func (c *ContainerWrapper) Supply(value interface{}, opts ...dig.ProvideOption) error
Supply a value into container. for example
c := digpro.New() digpro.QuickPanic( // register object c.Supply("a"), // equals to // c.Provide(func() string {return "a"}), ) foo, err := c.Extract(string("")) if err != nil { digpro.QuickPanic(err) } fmt.Println(foo) // Output: a
Example ¶
package main import ( "fmt" "github.com/rectcircle/digpro" ) func main() { c := digpro.New() digpro.QuickPanic( // register object c.Supply("a"), // equals to // c.Provide(func() string {return "a"}), ) foo, err := c.Extract(string("")) if err != nil { digpro.QuickPanic(err) } fmt.Println(foo) }
Output: a
func (*ContainerWrapper) Unwrap ¶
func (c *ContainerWrapper) Unwrap() *dig.Container
Unwrap *ContainerWrapper to obtain *dig.Container.
WARNING: the methold only for debug, please not use in production
func (*ContainerWrapper) Visualize ¶
func (c *ContainerWrapper) Visualize(w io.Writer, opts ...dig.VisualizeOption) error
Visualize for write dot graph to io.Writer
type ExtractOption ¶
type ExtractOption = internal.ExtractOption
func ExtractByGroup ¶
func ExtractByGroup(name string) ExtractOption
ExtractByGroup, for example
c := digpro.New() _ = c.Supply(1, dig.Group("ints")) // please handle error in production _ = c.Supply(1, dig.Group("ints")) is, _ := c.Extract(int(0), digpro.ExtractByGroup("ints")) fmt.Println(reflect.DeepEqual(is.([]int), []int{1, 1})) // true
func ExtractByName ¶
func ExtractByName(name string) ExtractOption
ExtractByName, for example
c := digpro.New() _ = c.Supply(1, dig.Name("int")) // please handle error in production i, _ := c.Extract(int(0), digpro.ExtractByName("int")) fmt.Println(i.(int) == 1) // true