This may be part of a solution that brings the Spring mindset into Go.
As per Go Programming Blueprints: https://www.safaribooksonline.com/library/view/go-programming-blueprints/9781786468949/ch10s03.html
Method receiver to carry dependencies into service layer.
Define struct to contain dependencies:
type vaultService struct{}
When creating a service:
// NewService makes a new Service.
func NewService() Service {
return vaultService{}
}
If the implementation did require any dependencies (such as a database connection or a configuration object), you could store them inside the struct and use the method receivers in your function bodies.
func (vaultService) Hash(ctx context.Context, password string) (string, error) {....}
An improvement on this concept is provided by:
https://godoc.org/github.com/facebookgo/inject
See: http://blog.parse.com/learn/engineering/dependency-injection-with-go/
Its use involves you seeding the object graph with some (possibly incomplete) objects, where the underlying types have been tagged for injection. Given this, the library will populate the objects creating new ones as necessary. It uses singletons by default, supports optional private instances as well as named instances.
The usage pattern for the library involves struct tags. It requires the tag format used by the various standard libraries, like json, xml etc. It involves tags in one of the three forms below:
`inject:""` `inject:"private"` `inject:"dev logger"`
So, in the Go world. The equivalent of wiring up the Spring application context would be found in a main method for your app:
func main() {
// Typically an application will have exactly one object graph, and
// you will create it and use it within a main function:
var g inject.Graph
var a HomePlanetRenderApp
err := g.Provide(
&inject.Object{Value: &a},
&inject.Object{Value: http.DefaultTransport},
)
...
This is using the inject library to do the wiring. inject.Graph is behaving like the Spring application context.
In the above code you can see dependency injection at work using the Provide method to wire up a dependency implementation to the graph.
An import note is in the example:
// it is an interface the library cannot create an instance
// for it. Instead it will use the given DefaultTransport to satisfy
// the dependency since it implements the interface:
The actual dependency is defined in the code as:
type NameAPI struct {
// Here and below in PlanetAPI we add the tag to an interface value.
// This value cannot automatically be created (by definition) and
// hence must be explicitly provided to the graph.
HTTPTransport http.RoundTripper `inject:""`
}
So - it appears that the inject library can auto create dependencies our use the versions pre-wired in the graph. This seems to something like lazy instantiation in spring beans.
type HomePlanetRenderApp struct {
// The tags below indicate to the inject library that these fields are
// eligible for injection. They do not specify any options, and will
// result in a singleton instance created for each of the APIs.
NameAPI *NameAPI `inject:""`
PlanetAPI *PlanetAPI `inject:""`
}
Since NameAPI and PlanetAPI are structs - the inject framework can instantiate on the fly vs having to use Provide as with the httpRoundTripper
No comments:
Post a Comment