Golang 中的接口


2022年1月19日, 学习电子教程
1980

在本教程中,您将学习 Golang 中的接口。包括接口的一些基本知识,例如 Golang 中的接口是什么以及如何在 Go 编程语言中声明接口。我们还将考虑接口与结构体之间的区别。此外,您将学习如何使用接口实现 Go 程序。

Golang 中的接口是什么?

接口是一种机制,通过它任何不相关的实体可以相互交互。它主要描述了一个实体的行为。实体是任何物理对象。
例如,如果一个东西像狗一样吠叫、移动、进食或咬人,那么这个东西就可以被识别为一只狗。狗的类型并不是我们关注的重点,我们只关注它的行为。
让我们用一个例子来理解这个概念。

GO : Interface

考虑一个电源插座和一些需要电源才能工作的电器设备,如电视、水壶、笔记本电脑、打印机。插座不知道将插入其中的各种电器设备来供电。这些设备需要连接到插座才能获取电源。因此,为了连接到插座,这些设备需要一个通用的接口。一个电源插座接口充当插座和电器设备之间的接口,以实现它们的连接并运行。电源插座为任何连接的设备供电。插座有一个插头方法,可以接受任何具有抽电方法的设备。每个电器设备都有一个抽电方法来从插座获取电源。

GO : Interface
  • 插座可以为任何设备供电。
  • 要供电,应该有一个抽电方法,即电源抽屉。
  • 在这个例子中,电源插座不知道所有设备的类型。
  • 设备需要从电源插座获取电源。
  • 因此,电器设备实现了一个电源抽屉接口,为此它们使用抽电方法。
  • 插座使用抽电方法为设备供电。
  • 简而言之,接口将不同类型彼此耦合,这有助于创建更易于维护的程序。
  • 您可以添加更多电器设备,而无需更改插座的类型。

注意:接口是一种抽象类型的协议,它没有实现,只描述了类型所期望的行为。

让我们考虑另一个例子,一个电视遥控器,它充当用户和电视之间的接口。设备遥控器帮助用户与电视进行交互。

GO : Interface

另一个例子是 API(应用程序编程接口),它在软件的前端和后端之间提供了一个接口。前端是用户可见的部分,后端是处理发生的地方。

在 Golang 编程中,接口列出了特定类型可以执行的函数。基本上,在接口中,您可以定义特定类型可以执行的操作。以人类为例,人类可以执行的活动,如吃饭、睡觉、走路等。因此,可以归类为执行这些任务的任何事物都可以是人类。

注意:接口不被实现,它只是定义了一个特定类型可以执行的操作,而这个类型被实现而不是定义的接口。

接口定义了一组可用的操作/方法。

Golang 中的具体类型是什么?

具体类型是抽象类型的反义词。除接口类型外,所有类型都是具体类型。

GO : Interface

注意:具体类型由所有非接口类型组成。

接口类型是什么?

  • 接口类型是一组方法签名。
  • 方法签名由方法名称和参数列表组成,包括参数的类型、数量和顺序。
  • 接口类型持有任何实现接口类型内部定义的方法的值。

如何声明接口?

在Go编程语言中,接口是一种包含一组方法的类型。接口形成方法或方法签名的集合,定义了类似类型实体或对象的行为。
定义接口的语法:


type<interface name=""> keyword interface {
method1
method2
            …….
}

在上述语法中,`type keyword interface`,表示特定名称的类型是一个接口。然后打开一个花括号,其中包含所有方法签名,如`method1, method2`等,语法以闭合花括号结束。
让我们看一个例子


 type shape interface {
   area () float64
}

语法定义了一个名为 `shape` 的接口类型,并在花括号内定义了一个 `area()` 方法,其类型为 `float64`。

GO : Interface

注意:接口只定义了预期的行为。

如何在 Golang 中实现接口?

让我们通过下面的程序来理解接口是什么以及如何实现接口。

在该程序中,有一个具有相似行为的圆形和矩形。并且包含两个函数来调用圆形面积和矩形面积。这两个函数虽然定义了不同的实现,但都具有共同的面积。
所以根据理论,你知道圆形和矩形都有一些形状和面积。

接口允许你将这些类型视为相同,并隐藏了底层细节,只关注事实,这里的事实是它们都有面积。
接口定义了一些对象之间或类型之间相似的行为。下面给出的类型是同一种,具有相关的行为。


type circle struct{
 radius float64
}
type rectangle struct{
 length float64
 breadth float64
}

在程序中,我们为圆创建了一个 切片 C1,为矩形创建了一个切片 R1。声明了一个带有一些类型用于 C1 和 R1 的切片 `shape`。假设这里的类型是未知的。

shapes :=[]type{C1,R1}

为了识别类型,我们需要定义如下接口


type shape interface{
  area() float64
}

因为圆形和矩形两种函数(func)都有一个名为 area() 的方法,所以它们都实现了 `shape` 接口。

GO : Interface

从上面的讨论中,您了解到接口可以作为任何具体类型使用。我们已经知道了在切片声明时应该使用的类型,您可以将那里提到的类型替换为接口类型,即如下所示的 `shape`。

shapes :=[]shape{C1,R1}

圆形和矩形都实现了 `shape` 接口,您可以将类型用作 `shape` 并将其放入定义的切片中。即使在接口声明之后,函数 `circle` 和 `rectangle` 也无法通过接口访问。为了访问它们,我们使用点操作符。`shape.area()` 访问圆形和矩形内部的字段,这反过来又在下面的程序中放入 `for` 循环语句中,例如


for _,shape := range shapes{
 fmt.Println(shape.area())

现在让我们看一下下面给出的完整代码,它打印圆形和矩形的面积。

GO : Control-flow

带接口的程序


package main
import (
     "fmt"
     "math"
)
type shape interface{
  area() float64
}

type circle struct{
 radius float64
}


type rectangle struct{
 length float64
 breadth float64
}

func (r rectangle) area() float64{
return r.length * r.breadth
}

func (c circle) area() float64{
return math.Pi * c.radius *c.radius
}

func main(){
C1 := circle{2}
R1 :=rectangle{5,2}
shapes :=[]shape{C1,R1}

for _,shape := range shapes{
 fmt.Println(shape.area())
}
}

输出


12.566370614359172
10

注意:接口可以与任何类型的类型一起使用,在上面的程序中,我们将其用作切片类型,它也可以是变量类型、返回类型、参数类型等。所有这些不同类型的都可以用于接口类型之下。

Golang 中的 Stringer 是什么?

Stringer 是 `fmt` 包中实现的一种类型。Stringer 类型将自身描述为字符串。`fmt` 包使用 Stringer 接口来打印值。

创建 Stringer 的语法


type Stringer interface {
    String () string
}

其中

  • type 是一个关键词,
  • Stringer 是接口名称
  • interface 是一个关键字
  • String () 是 Stringer 接口中唯一的字符串类型方法。

如何实现 Stringer 接口?

Stringer 是一个自动化方法创建的工具,该方法满足 `fmt.Stringer` 接口。

语法


func (t T) String() string{

}

示例


package main
func (s SITE) String() string {
 return s.Name
}

在给定程序中,声明了一个新的 `SITE` 类型。主函数包含类型为 `SITE` 的实例“S”。当运行下面给出的代码时,将获得打印结构字段值(即 Name、language、year、tutorial)的输出。

使用 Stringer 接口之前的程序


package main
import (
 "fmt"
)

/*A struct is a type which contains named fields.
Define new type named 'SITE'*/
type SITE struct {
  Name    string
 language    string
 year  int
 tutorial []string
}
func main() {

 /*initialize a struct.
   Create an instance of type 'SITE'*/
 S := SITE{"learn eTutorials","GO", 2022,[]string{"JAVA", "C"}}
 fmt.Println(S)
}

输出


{learn eTutorials GO 2022 [JAVA C]}

可以按如下所示更改文本输出

输出


{learn eTutorials GO 2022 [JAVA C]}

`stringer` 接口的 `string` 方法用于实现此属性。


/**SITE  type implements the method "String" of "Stringer" interface.*/
func (s SITE) String() string {
 return s.Name
}

上述函数实现了 `Stringer` 接口的 `string` 方法,其中类型是 `SITE`,当您运行代码时,它将返回 `SITE` 的名称并打印输出“Learn tutorials”。

程序实现了 `stringer` 接口


/*A struct is a type which contains named fields.
Define new type named 'Person'*/
type SITE struct {
  Name    string
 language    string
 year  int
 tutorial []string
}

/**SITE  type implements the method "String" of "Stringer" interface.*/
func (s SITE) String() string {
 return s.Name
}
func main() {

 /*initialize a struct.
   Create an instance of type 'Person'*/
 S := SITE{"learn eTutorials","GO", 2022,[]string{"JAVA", "C"}}
 fmt.Println(S)
}

输出


Learn eTutorials

此 Stringer 接口允许覆盖行为。您可以通过将返回类型更改为 `return s.language` 来打印在结构体类型中定义的语言作为输出,这将打印语言“GO”。


**SITE type implements the method "String" of "Stringer" interface.*/
func (s SITE) String() string {
 return s.language 
}

输出


GO