在Golang中使用依赖注入的最佳方法是什么

时间:2017-09-10 14:40:23

标签: go dependency-injection

我是Golang的初学者,我正在开发一个小型库,需要在代码中的某个点获取数据库连接以进行不同的子包/方法调用。我只是想知道如何管理这个?

示例,如果我设法使用Web服务器,它可以使用处理程序,那么如何在此函数中获得此连接? 它可以与另一个进程,简单的方法调用或MVC模型一起使用吗?

我不想使用全局,因为对我来说这是一种不好的做法,除非它是非常特殊的方式(或者某种方式很棘手)。

我在不同的网站上阅读了很多写作,但我仍然在询问和学习不同的观点和经验。

谢谢你的时间!

5 个答案:

答案 0 :(得分:2)

创建一个代表资源的结构,让我们调用Cart。将get和post方法添加到此结构中。这些方法应该是http处理程序。在main中使用db接口创建struct的实例。并在路线中调用Cart.get。现在在get方法中,您可以访问db接口。

不是一个有效的例子,只是为了获得注入测试的想法。

type storage interface {
    PrepareContext(context.Context, string) (*sql.Stmt, error)
}

func main() {
    db, _ := sql.Open("mysql", `queryString`)
    http.HandleFunc("/", Cart{db}.get)
    http.ListenAndServe(":8080", nil)
}

type Cart struct {
    storage
}

func (crt Cart) get(w http.ResponseWriter, r *http.Request) {
    q, _ := crt.PrepareContext(context.Background(), `select *`)
    fmt.Println(q.Exec())
}

/////////Test
type testDB struct{}

func (c testDB) PrepareContext(context.Context, string) (*sql.Stmt, error) {
    return nil, nil
}
func TestGet(t *testing.T) {
    db := testDB{}
    _ = Cart{db}

    //http test here
}

答案 1 :(得分:0)

我建议试试https://github.com/facebookgo/inject。它允许定义对象图并使用struct注释指定依赖关系。使用反射进行注射。

答案 2 :(得分:0)

我建议使用Dargo,它是Java CDI和/或JSR-330风格的注入引擎。它使用结构注释,并使用反射或使用创建者函数执行注入。它支持服务的不同生命周期,包括Singleton(延迟创建一次,仅创建一次),PerLookup(每次注入或查找每次创建),Instant(立即创建,一次创建)和DargoContext(绑定到context.Context的生命周期)

答案 3 :(得分:0)

您还可以尝试Hiboot,它是一个Web / cli应用程序框架,支持开箱即用的依赖项注入。

Docs

// HelloService is a simple service interface, with interface, we can mock a fake service in unit test
type HelloService interface {
    SayHello(name string) string
}

type helloServiceImpl struct {
}

func init() {
    // Register Rest Controller through constructor newHelloController
    // Register Service through constructor newHelloService
    app.Register(newHelloController, newHelloService)
}

// please note that the return type name of the constructor HelloService,
// hiboot will instantiate a instance named helloService for dependency injection
func newHelloService() HelloService {
    return &helloServiceImpl{}
}

// SayHello is a service method implementation
func (s *helloServiceImpl) SayHello(name string) string {
    return "Hello" + name
}

// PATH: /login
type helloController struct {
    web.Controller
    helloService HelloService
}

// newHelloController inject helloService through the argument helloService HelloService on constructor
func newHelloController(helloService HelloService) *helloController {
    return &helloController{
        helloService: helloService,
    }
}

// Get /
// The first word of method name is the http method GET
func (c *helloController) Get(name string) string {
    return c.helloService.SayHello(name)
}

答案 4 :(得分:0)

对于IoC容器,您可以尝试以下软件包: https://github.com/golobby/container

单例绑定的示例:

container.Singleton(func() Database {
  return &MySQL{}
})

解决示例:

var db Database
container.Make(&db)

如您所见,它是如此容易使用。