在 go 中使用接口进行依赖注入

Dependency injection with interface in go

我有一个结构 StructDependingOnInterface 依赖于 MyInterface 接口。我希望在实例化 StructDependingOnInterface 时将结构 Implementation 注入到 bar 中。

我试过用 facebookgo/inject 库来做这个,但它似乎不适用于接口。 s.bar 始终为零。

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

go 语言是否允许我尝试做的事情?

是否有 facebookgo/inject 的替代品可以满足我的需要?

facebookgo/inject should be able to handle interfaces, look at the example in the link and how they use http.RoundTripperhttp.DefaultTransport.

首先您需要导出 bar,即将其更改为 Bar。然后你还需要将 s 传递给 Provide 以获得 g.Populate 然后才能设置 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 是一个 cli/web 框架,支持用 Go 编写的依赖注入。

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

Hiboot概述
  • Web MVC(模型-视图-控制器)。
  • 自动配置,使用属性配置为依赖注入预创建实例。
  • 使用结构标签名称 inject:"" 或构造函数的依赖注入。
示例代码:
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
}