There are Go packages that help with dependency injection, employing 
reflection.
And other practices insist on passing everything as an argument, down the 
pipe; employing mostly factory methods.
At the same time putting long-lived instances inside a context is not 
recommended - I like context for cancellation (and hierarchy of 
cancellations) and I like it for passing state when every step in a 
pipeline is concurrent and short lived; for other uses, using context seems 
a not proper choice.

Struggling with these thoughts, something like a hierarchical service 
locator came to my mind:

type DepRegistry struct {
 parent *DepRegistry
 deps   sync.Map
}


func (r *DepRegistry) Register(name string, dep interface{}) {
 r.deps.Store(name, dep)
}


// Load first loads from current instance, then tries
// to load from parent (panics if fails to find)
func (r *DepRegistry) Load(name string) interface{} {
 dep, ok := r.deps.Load(name)
 if !ok {
 if r.parent != nil {
 return r.parent.Load(name)
 }
 panic("unknown dep " + name)
 }
 return dep
}


func NewDepRegistry(parent ...*DepRegistry) *DepRegistry {
 res := &DepRegistry{}
 if len(parent) > 0 && parent[0] != nil {
 res.parent = parent[0]
 }
 return res
}


I would love to hear thoughts on this matter. Is it an acceptable solution? 
Is there anything missing?

Sample App: There is this app, with different packages that are using 
services like logging, creating/modifying images, sending/receiving 
messages from bots and the like. Those parts are already separate 
executables, communication via NATS. 

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to