Skip to content

Commit

Permalink
docs(depinject): replace non-exported provider functions
Browse files Browse the repository at this point in the history
Close cosmos#17743

Since cosmos#12797, it's no longer possible to use non-exported functions as
providers. The README used to contain examples with function literals as
provider, so this change replaces them with exported functions.

An additional change updates the `BindInterface` arguments, which wasn't
working on my side when running this code in go module called "duck".
  • Loading branch information
tbruyelle committed Sep 15, 2023
1 parent c92b257 commit a5ffd60
Showing 1 changed file with 45 additions and 27 deletions.
72 changes: 45 additions & 27 deletions depinject/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,20 @@ import (

type AnotherInt int

func GetInt() int { return 1 }
func GetAnotherInt() AnotherInt { return 2 }

func main() {
var (
x int
y AnotherInt
x int
y AnotherInt
)

fmt.Printf("Before (%v, %v)\n", x, y)
depinject.Inject(
depinject.Provide(
func() int { return 1 },
func() AnotherInt { return AnotherInt(2) },
GetInt,
GetAnotherInt,
),
&x,
&y,
Expand All @@ -66,7 +69,7 @@ func main() {

In this example, `depinject.Provide` registers two provider functions that return `int` and `AnotherInt` values. The `depinject.Inject` function is then used to inject these values into the variables `x` and `y`.

Provider functions serve as the basis for the dependency tree. They are analysed to identify their inputs as dependencies and their outputs as dependents. These dependents can either be used by another provider function or be stored outside the DI container (e.g., `&x` and `&y` in the example above).
Provider functions serve as the basis for the dependency tree. They are analysed to identify their inputs as dependencies and their outputs as dependents. These dependents can either be used by another provider function or be stored outside the DI container (e.g., `&x` and `&y` in the example above). Provider functions must be exported.

### Interface type resolution

Expand Down Expand Up @@ -98,17 +101,32 @@ type Pond struct {
}
```

And the following provider functions:

```go
func GetMallard() duck.Mallard {
return Mallard{}
}

func GetPond(duck Duck) Pond {
return Pond{Duck: duck}
}

func GetCanvasback() Canvasback {
return Canvasback{}
}
```

In this example, there's a `Pond` struct that has a `Duck` field of type `AlsoDuck`. The `depinject` framework can automatically resolve the appropriate implementation when there's only one available, as shown below:

```go
var pond Pond

depinject.Inject(
depinject.Provide(
func() Mallard { return Mallard{} },
func(duck Duck) Pond {
return Pond{Duck: duck}
}),
GetMallard,
GetPond,
),
&pond)
```

Expand All @@ -120,13 +138,12 @@ However, if there are multiple implementations of the `Duck` interface, as in th
var pond Pond

depinject.Inject(
depinject.Provide(
func() Mallard { return Mallard{} },
func() Canvasback { return Canvasback{} },
func(duck Duck) Pond {
return Pond{Duck: duck}
}),
&pond)
depinject.Provide(
GetMallard,
GetCanvasback,
GetPond,
),
&pond)
```

A specific binding preference for `Duck` is required.
Expand All @@ -137,17 +154,18 @@ In the above situation registering a binding for a given interface binding may l

```go
depinject.Inject(
depinject.Configs(
depinject.BindInterface(
"duck.Duck",
"duck.Mallard"),
depinject.Provide(
func() Mallard { return Mallard{} },
func() Canvasback { return Canvasback{} },
func(duck Duck) APond {
return Pond{Duck: duck}
})),
&pond)
depinject.Configs(
depinject.BindInterface(
"duck/duck.Duck",
"duck/duck.Mallard",
),
depinject.Provide(
GetMallard,
GetCanvasback,
GetPond,
),
),
&pond)
```

Now `depinject` has enough information to provide `Mallard` as an input to `APond`.
Expand Down

0 comments on commit a5ffd60

Please sign in to comment.