依赖注入是一种使用Go接口的技术。

huangapple go评论87阅读模式
英文:

Dependency injection using go interface

问题

我正在尝试使用一些依赖注入,通过Go接口来实现,这是在阅读一些相关文档后得出的结论。

我有两个方法应该实现同一个接口:

type Shooter interface {
    Spec(ev v1alpha1.Ev) (v1beta1.Shoot, error)
}

type Project struct {
    Name string
}

具体的实现在这里:

例如:

func (n Project) Spec(ev v1alpha1.Ev) (v1beta1.Shoot, error) {
    var shoot = v1beta1.Shoot{}
    fmt.Println(shoot, ev)
    return shoot, nil
}

现在我想在上面的包中获取具体的实现,我尝试了以下方法:

func kind(ev v1alpha1.Ev, namespace string) (v1beta1.Shoot, error) {
    var shoot v1beta1.Shoot
    var e error
    switch ev.Spec.Infrastructure.Type {
    case "gcp":
        project := gcp.Project{Name: namespace}
        shoot, e = project.Spec(ev)
        if e != nil {
            return v1beta1.Shoot{}, e
        }

但是它不起作用,有任何想法如何正确实现吗?

英文:

Im trying to use some dependency injection via go interface after reading some docs about it.

I’ve two methods which should implement one interface

type Shooter interface {
	Spec(ev v1alpha1.Ev) (v1beta1.Shoot, error)
}

type Project struct {
	Name string
}

https://github.com/JennyMet/testint/blob/master/internal/infra/common.go#L8

The concrete implementation is here
https://github.com/JennyMet/testint/blob/master/internal/infra/azure/azure.go#L13
https://github.com/JennyMet/testint/blob/master/internal/infra/gcp/gcp.go#L13

e.g.

func (n Project) Spec(ev v1alpha1.Ev) (v1beta1.Shoot, error) {
	var shoot = v1beta1.Shoot{}
	fmt.Println(shoot, ev)
	return shoot, nil
}

Now I want to get the specific implementation in package above and I tried the following

https://github.com/JennyMet/testint/blob/master/internal/infra/provider.go#L16

func kind(ev v1alpha1.Ev, namespace string) (v1beta1.Shoot, error) {
	var shoot v1beta1.Shoot
	var e error
	switch ev.Spec.Infrastructure.Type {
	case "gcp":
		project := gcp.Project{Name: namespace}
		shoot, e = project.Spec(ev)
		if e != nil {
			return v1beta1.Shoot{}, e
		}

But it doesn’t works, any ideas how can I do it right?

答案1

得分: 1

但它不起作用

没有明确指定,但我假设依赖注入不起作用。

注入需要至少两种不同的实体类型。一个是被注入的实体,另一个是接收注入的目标。

在你的情况下,你只有一个 - 在gcpazure中实现的注入。

你需要添加一个包含被注入接口的目标:

type Target struct {
    Specer Shooter
}

func (t *Target) DoWork() {
   // 在这里,你可以使用t.Specer.Spec(),而不需要知道具体的实现细节
}

现在你可以使用依赖注入创建Target

func NewTarget(specer Shooter) *Target{
        return &Target{
          Specer: specer,
        } 
}

你的代码通常在应用程序启动时非常接近组合根中决定所有使用的类型并进行注入(调用NewTarget())。

更新:

接口也可以注入到函数中。这也是依赖注入:

func kind(ev v1alpha1.Ev, namespace string, specer Shooter) (v1beta1.Shoot, error) {
   ...
   shoot, e = specer.Spec(ev)
   ...
}

这是一种称为服务定位器的模式的替代方法:

func kind(ev v1alpha1.Ev, namespace string) (v1beta1.Shoot, error) {
   ...
   specer := factory.GetSpecer()
   shoot, e = specer.Spec(ev)
   ...
}

服务定位器经常被称为反模式。

英文:

> But it doesn’t works

It is not specified, but I assume that Dependency Injection does not work.

Injection requires at least two different entity types. One is injected and the second on is a target receiving that injection.

In your case, you have only one - Injection implemented in two forms gcp and azure.

You need to add a target that contains injected interface:

type Target struct {
    Specer Shooter
}

func (t *Target) DoWork() {
   // here you can use t.Specer.Spec() without knowing implementation details
}

Now you can create Target using DI:

func NewTarget(specer Shooter) *Target{
        return &Target{
          Specer: specer,
        } 
}

Your code typically decides on all used types and injects them (calling NewTarget()) very close to application start in Composition Root

Update:

Interface is also can be injected into function. It is also Dependency Injection:

func kind(ev v1alpha1.Ev, namespace string, specer Shooter) (v1beta1.Shoot, error) {
   ...
   shoot, e = specer.Spec(ev)
   ...
}

That is an alternative to a pattern called Service Locator:

func kind(ev v1alpha1.Ev, namespace string) (v1beta1.Shoot, error) {
   ...
   specer := factory.GetSpecer()
   shoot, e = specer.Spec(ev)
   ...
}

Service Locator often referred as antipattern.

huangapple
  • 本文由 发表于 2022年7月14日 02:57:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/72971324.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定