简体   繁体   中英

Dependency injection with interface in go

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 ?

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 , ie 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()
}

hiboot is an cli/web framework that support dependency injection written in Go.

Code: https://github.com/hidevopsio/hiboot

Hiboot Overview
  • Web MVC (Model-View-Controller).
  • Auto Configuration, pre-create instance with properties configs for dependency injection.
  • Dependency injection with struct tag name inject:"" or Constructor func.
Sample Code:
 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 } 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM