-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
103 lines (86 loc) · 3.04 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package main
import (
"context"
"os"
"time"
"github.com/sirupsen/logrus"
"github.com/phramz/dimple"
)
// each definition in the container need an ID so it could be referenced. It might be a good idea to introduce
// constants for this since it could make your life easier when it comes to refactoring stuff.
// though any string is fine ... make sure that its somehow unique otherwise you might overwrite another
// by accident definition with the same id
const (
ServiceLogger = "logger"
ServiceTime = "service.time"
ParamTimeFormat = "config.time_format"
)
// go run main.go
func main() {
// with the Builder we can configure the container
builder := dimple.Builder(
// let's add our favorite time format as parameter to the container so other services can pick it up
dimple.Param(ParamTimeFormat, time.Kitchen),
// we can just add an anonymous function as factory for our "logger" service since it does not depend on other services
// and therefore does not need any context
dimple.Service(ServiceLogger, dimple.WithFn(func() any {
logger := logrus.New()
logger.SetOutput(os.Stdout)
return logger
})),
// this service depends on the "logger" to output the time and "config.time_format" for the desired format.
// that is why we need to use WithContextFn to get to the container and context
dimple.Service(ServiceTime, dimple.WithContextFn(func(ctx dimple.FactoryCtx) (any, error) {
// you get can whatever dependency you need from the container as
// long as you do not create a circular dependency
logger := dimple.MustGetT[*logrus.Logger](ctx.Container(), ServiceLogger)
format := dimple.MustGetT[string](ctx.Container(), ParamTimeFormat)
return &TimeService{
logger: logger.WithField("service", ctx.ServiceID()),
format: format,
}, nil
})),
)
// once we're done building we can retrieve a new instance of Container
container, err := builder.Build(context.Background())
if err != nil {
panic(err)
}
// this is not necessary, but recommend since it will instantiate all service eager and
// would return an error if there are issues. We don't want it to panic during runtime but rather error on startup
if err = container.Boot(); err != nil {
panic(err)
}
go func() {
// retrieve the *TimeService instance via generic function. Beware that illegal type assertions will panic
timeService := dimple.MustGetT[*TimeService](container, ServiceTime)
// if you want to handle error you might consider this approach:
//
// val, err := container.Get(ServiceTime)
// if err != nil {
// panic("cannot instantiate service")
// }
// timeService, ok := val.(*TimeService)
// if !ok {
// panic("illegal type assertion")
// }
for {
select {
case <-container.Ctx().Done():
return
default:
// we will output the time every second
time.Sleep(time.Second)
timeService.Now()
}
}
}()
<-container.Ctx().Done()
}
type TimeService struct {
logger *logrus.Entry
format string
}
func (t *TimeService) Now() {
t.logger.Infof("It is %s", time.Now().Format(t.format))
}