// The [sl] package has two main concepts, the [ServiceLocator] itself is the main object that one should pass around through the application. A [ServiceLocator] has a list of slots that can be filled with [InjectLazy] and [InjectValue] and retrieved with [Use]. As slots should be unique they can only be created with the [NewSlot] function.
//
// The usual way to use this module is to make slots for go interfaces and then pass implementations using the [InjectValue] and [InjectLazy] functions.
packagesl
import(
"fmt"
"log"
"os"
)
typeSlotKey[Tany]*struct{}
// Logger is the debug logger, in the future this will be disabled and discard by default.
//
// As this is the service locator module it was meaning less to pass this through the ServiceLocator itself (without making the whole module more complex)
// NewSlot is the only way to create instances of the slot type. Each instance is unique.
//
// This then lets you attach a service instance of type "T" to a [ServiceLocator] object.
funcNewSlot[Tany]()slot[T]{
returnslot[T](new(struct{}))
}
typeslotstruct{
// slotEntry represents a service that can lazily initialized (using "createFunc"). Once initialized the instance is kept in the "value" field. The field "typeName" just for debugging purposes.
// ServiceLocator is the main context passed around to retrive service instances, the interface uses generics so to inject and retrive service instances you should use the functions [InjectValue], [InjectLazy] and [Use].
typeServiceLocatorstruct{
providersmap[any]*slot
providersmap[any]*slotEntry
}
// New creates a new [ServiceLocator] context to pass around in the application.
log.Printf(`injected value of type %T for slot of type %s`,value,getTypeName[T]())
// InjectValue will inject a concrete instance inside the ServiceLocator "l" for the given "slotKey". This should be used for injecting "static" services, for instances whose construction depend on other services you should use the [InjectLazy] function.
//
// This is generic over "T" to check that instances for the given slot type check as "T" can also be an interface.
log.Printf(`injected lazy for slot of type %s`,getTypeName[T]())
// InjectLazy will inject an instance inside the given ServiceLocator and "slotKey" that is created only when requested with a call to the [Use] function.
//
// This is generic over "T" to check that instances for the given slot type check as "T" can also be an interface.
// Use retrieves the value of type T associated with the given slot key from the provided ServiceLocator instance.
//
// If the ServiceLocator does not have a value for the slot key, or if the value wasn't correctly initialized (in the case of a lazy slot), an error is returned.