Reputation: 1024
I have a struct StructDependingOnInterface
which depends on MyInterface
interface. I'd like the struct Implementation
to be injected into bar
when StructDependingOnInterface
is instantiated.
I have tried doing this with facebookgo/inject library, but it seems like it doesn't work with interfaces. s.bar
is always nil.
package main
import (
"fmt"
"log"
"github.com/facebookgo/inject"
)
type MyInterface interface {
Foo()
}
type Implementation struct{}
func (imp *Implementation) Foo() {
fmt.Println("Hello")
}
type StructDependingOnInterface struct {
bar MyInterface `inject:""`
}
func main() {
var g inject.Graph
err := g.Provide(
&inject.Object{Value: &Implementation{}},
)
if err != nil {
log.Fatal(err)
}
g.Populate()
s := &StructDependingOnInterface{}
s.bar.Foo()
}
Does the language go allows what I'm trying to do ?
Is there an alternative of facebookgo/inject that would fits my need ?
Upvotes: 2
Views: 4036
Reputation: 29
Code:
https://github.com/hidevopsio/hiboot
inject:""
or Constructor func.package main
import (
"github.com/hidevopsio/hiboot/pkg/app/web"
"github.com/hidevopsio/hiboot/pkg/model"
"github.com/hidevopsio/hiboot/pkg/starter/jwt"
"time"
)
// This example shows that token is injected through constructor,
// once you imported "github.com/hidevopsio/hiboot/pkg/starter/jwt",
// token jwt.Token will be injectable.
func main() {
// create new web application and run it
web.NewApplication().Run()
}
// PATH: /login
type loginController struct {
web.Controller
token jwt.Token
}
type userRequest struct {
// embedded field model.RequestBody mark that userRequest is request body
model.RequestBody
Username string `json:"username" validate:"required"`
Password string `json:"password" validate:"required"`
}
func init() {
// Register Rest Controller through constructor newLoginController
web.RestController(newLoginController)
}
// inject token through the argument token jwt.Token on constructor newLoginController, you may wonder why is token come from
// well, it provided by hiboot starter jwt, see above hiboot link for more details
func newLoginController(token jwt.Token) *loginController {
return &loginController{
token: token,
}
}
// Post /
// The first word of method is the http method POST, the rest is the context mapping
func (c *loginController) Post(request *userRequest) (response model.Response, err error) {
jwtToken, _ := c.token.Generate(jwt.Map{
"username": request.Username,
"password": request.Password,
}, 30, time.Minute)
response = new(model.BaseResponse)
response.SetData(jwtToken)
return
}
Upvotes: 0
Reputation: 38233
facebookgo/inject should be able to handle interfaces, look at the example in the link and how they use http.RoundTripper
and http.DefaultTransport
.
First you need to export bar
, i.e. changing it to Bar
. Then you also need to pass s
to Provide
for g.Populate
to then be able to set Bar
.
type StructDependingOnInterface struct {
Bar MyInterface `inject:""`
}
func main() {
var g inject.Graph
s := &StructDependingOnInterface{}
err := g.Provide(
&inject.Object{Value: s},
&inject.Object{Value: &Implementation{}},
)
if err != nil {
log.Fatal(err)
}
if err := g.Populate(); err != nil {
log.Fatal(err)
}
s.bar.Foo()
}
Upvotes: 3