#
Register Constructor Functions
In Parsely, the fundamental way to register services is by providing a constructor function to the service registry. This method enables you to create instances of your services in a controlled manner and inject them into your application as needed.
#
What is a constructor function?
In Go, a constructor function is a regular function used to initialize and return an instance of a type. It typically follows the pattern NewTypeName
and allows for setting up a struct with necessary values or configurations before returning it. Unlike languages with built-in constructors, Go doesn't have special constructor syntax, so developers create these functions explicitly to manage object initialization and ensure type safety. For example, a constructor for the greeter
struct might be NewGreeter() *greeter
or NewGreeter() Greeter
if interfaces are preferred.
When registering a constructor function for a service type, Parsley inspects the given function upon service resolution and automatically determines the required services. Constructor functions must also be registered for required services so that Parsley can construct the whole tree of dependencies and pass service instances as needed.
#
Example
Here’s a basic example of registering a service using a constructor function:
registry := registration.NewServiceRegistry()
_ = registration.RegisterTransient(registry, internal.NewGreeter)
In this example, the NewGreeter
function is used to create instances of the Greeter
interface. This function returns an implementation of Greeter
while hiding the concrete type *greeter
.
The Greeter
interface and its implementation are defined as follows:
package internal
import "fmt"
type Greeter interface {
SayHello(name string, polite bool)
}
type greeter struct{}
func (g *greeter) SayHello(name string, polite bool) {
if polite {
fmt.Printf("Good day, %s!\n", name)
} else {
fmt.Printf("Hello, %s\n", name)
}
}
func NewGreeter() Greeter {
return &greeter{}
}
While it’s possible for NewGreeter
to return a *greeter
directly, it is generally advisable to return the interface type Greeter
. This approach maintains flexibility and abstraction, making it easier to change implementations without modifying dependent code.