Sorry, forgot about mentioning the very language the OP was about. That was stupid.
You would use the "New" constructor function pattern in this case, using a higher order function called at injection time to keep it reusable and hide everything. I also prefer keeping the struct it returns as unexported so you get full encapsulation, but golint doesn't like it. I guess this is a personal issue.
> You would use the "New" constructor function pattern in this case, using a higher order function called at injection time to keep it reusable and hide everything.
Spot on. I love the decorator pattern for dependency injection.
type Server struct {
logger *logrus.Logger // optional
store databaste.Store // required
}
type ServerOption func(Server) Server
func WithLogger(logger *logrus.Logger) ServerOption {
return func(s Server) Server {
s.logger = logger
return s
}
}
func NewServer(store database.Store, options ...ServerOption) *Server {
s := Server{store: store}
for _, option := range options {
s = option(s)
}
return &s
}
func main() {
myServer := NewServer(myStore, WithLogger(myLogger))
}
You would use the "New" constructor function pattern in this case, using a higher order function called at injection time to keep it reusable and hide everything. I also prefer keeping the struct it returns as unexported so you get full encapsulation, but golint doesn't like it. I guess this is a personal issue.