Golang包接口

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

Golang package interface

问题

我对golang还不太熟悉,关于包和接口方面我有一个问题。
如果我有一个需要使用接口实现的package1,并且将来可能需要用其他实现来替换,这种情况是否可行?

以下是伪代码示例:

implementation包包含接口的当前实现

type TestI interface {
   M1()
}
package implementation

type Impl struct {}

func (i *Impl) M1() {
   // 做一些操作
}
package package1

import "path/to/TestI" // 以某种方式导入TestI,并调用M1方法,但可以灵活地将其与接口的其他实现交换

package1应该在不知道具体实现的情况下使用接口(类似于C#或Java中的依赖注入,package1只需知道接口,而不需要知道具体实现)。
TestI接口应该在哪里定义?如果有点混乱,我很抱歉,我只是试图理清思路。

这在C#中的等效代码如下:

interface ITest {
  void SetClass(Class1 cl);
}

// package1
class Class1 {
  private ITest test;

  public void SomeMethod() {
    // 我希望以某种方式在其他包中设置这个
    test.SetClass(this);
  }
}

// package2
class Test : ITest {
  private Class1 c1;

  public void SetClass(Class1 c) {
    this.c1 = c;
  }
}
英文:

I am bit new to golang and I have a question about packages and interfaces.
If I have package1, that needs to use implementation of an interface that can be swapped in future with other implementation, would that be possible?

some pseudo code

package implementation contains current implementation of interface

type TestI interface {
   M1()
}
package implementation

type Impl struct {}

funct (i *Impl) M1 ( ... do something )

package package1

import TestI somehow and call M1 method but with flexibility to swap it with other implementation of this interface in future?

package package1 should use implementation without knowing about it (something like DI in c# or java, package should only know about interface, and not about implementation)
Where should TestI interface be defined? Sorry if this is a bit confusing, just trying to get my head around it.

This is equivalent in c#

ITest {
  SetClass(Class1 cl);
}

// package1
class Class1 {
  private ITest test {get; set;}

  public void SomeMethod() {
// i want to somehow set this in other package
    test.SetClass(this);
  }
}

// package2
class Test implements ITest {
 private Class1 cl;

SetClass(Class1 c) {
 this.c1 = c;
}

}

答案1

得分: 1

除非您正在编写一个以接口为先的应用程序,否则通常最好在不声明任何接口的情况下编写具体实现。然后,该包的用户可以声明所需的接口。例如:

type Implementation struct {
   ...
}

func (i Implementation) FuncA() {...}
func (i Implementation) FuncB() {...}

如果需要实现FuncA的某种类型,您可以声明:

type IntfA interface {
   FuncA()
}

任何具有方法FuncA的类型都实现了IntfA,而Implementation符合该描述,因此您可以将Implementation的实例传递给需要IntfA的函数。

类似地,如果您需要一个既有FuncA又有FuncB的接口,您可以声明:

type IntfAB interface {
   FuncA()
   FuncB()
}

Implementation也实现了IntfAB

因此,理想情况下,您应该在使用接口的地方声明所需的接口,任何具有匹配方法集的类型都可以用于实现该接口。

如果您是基于现有接口编写代码,那么您可以将该接口放在与实现不同的包中,或者您可以将接口和实现放在同一个包中,具体取决于您的用例。

英文:

Unless you are writing an interface-first application, it is generally best to write the concrete implementations without declaring any interfaces. Then the users of that package can declare the necessary interfaces. For example:

type Implementation struct {
   ...
}

func (i Implementation) FuncA() {...}
func (i Implementation) FuncB() {...}

If some type that implements FuncA is required, you can declare:

type IntfA interface {
   FuncA()
}

Any type that has the method FuncA implements IntfA, and Implementation fits that description, so you can pass an instance of Implementation to a function that needs IntfA.

Similarly, if you need an interface that has both FuncA and FuncB, you can declaret:

type IntfAB interface {
   FuncA()
   FuncB()
}

and Implementation also implements IntfAB.

So, ideally, you would declare the interface you need where you use it, and any type with a matching set of methods can be used for the implementation of that interface.

If you are writing based on an existing interface, then you can put that interface in a separate package than the implementation, or you can keep the interface and the implementation in the same package, whichever makes more sense for your use case.

huangapple
  • 本文由 发表于 2021年5月23日 10:21:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/67655618.html
匿名

发表评论

匿名网友

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

确定