实例讲解 Go 的 Interface

Go

Go 接口

Go中的接口是使用一组方法签名定义的类型。该接口为类似类型的对象定义行为。

例如,这是一个定义几何形状行为的接口:

// Go 接口 - `形状`
type Shape interface {
    Area() float64
    Perimeter() float64
}

使用** type **关键字声明接口,然后使用接口名称和关键字interface声明接口。然后,在花括号内指定一组方法签名。

在 Go 中实现接口

要实现接口,您只需实现接口中声明的所有方法。

Go接口是隐式实现的

与Java之类的其他语言不同,您无需明确指定类型使用诸如implements关键字之类的东西来实现接口。您只需实现接口中声明的所有方法即可。

这是两种实现Shape接口的Struct类型:

//结构类型`Rectangle`-通过实现其所有方法来实现`Shape`接口。
type Rectangle struct {
    Length, Width float64
}

func (r Rectangle) Area() float64 {
    return r.Length * r.Width
}

func (r Rectangle) Perimeter() float64 {
    return 2 * (r.Length + r.Width)
}
//结构类型`Circle`-通过实现其所有方法来实现`Shape`接口。
type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return math.Pi * c.Radius * c.Radius
}

func (c Circle) Perimeter() float64 {
    return 2 * math.Pi * c.Radius
}

func (c Circle) Diameter() float64 {
    return 2 * c.Radius
}

使用具有具体值的接口类型

除非我们将接口与实现其所有方法的具体类型一起使用,否则接口本身并不是那么有用。

让我们看看如何将接口与具体值一起使用。

-接口类型可以包含实现其所有方法的任何值

```
package main

import (
    "fmt"
)

func main() {
    var s Shape = Circle{5.0}
    fmt.Printf("Shape Type = %T, Shape Value = %v\n", s, s)
    fmt.Printf("Area = %f, Perimeter = %f\n\n", s.Area(), s.Perimeter())

    s = Rectangle{4.0, 6.0}
    fmt.Printf("Shape Type = %T, Shape Value = %v\n", s, s)
    fmt.Printf("Area = %f, Perimeter = %f\n", s.Area(), s.Perimeter())
}

```

```
# 输出
Shape Type = main.Circle, Shape Value = {5}
Area = 78.539816, Perimeter = 31.415927

Shape Type = main.Rectangle, Shape Value = {4 6}
Area = 24.000000, Perimeter = 20.000000

```
  • -使用接口类型作为函数的参数

    package main
    
    import (
        "fmt"
    )
    
    // 通用函数,用于计算不同类型的多个形状的总面积
    func CalculateTotalArea(shapes ...Shape) float64 {
        totalArea := 0.0
        for _, s := range shapes {
            totalArea += s.Area()
        }
        return totalArea
    }
    
    func main() {
        totalArea := CalculateTotalArea(Circle{2}, Rectangle{4, 5}, Circle{10})
        fmt.Println("Total area = ", totalArea)
    }
    
    # 输出
    Total area =  346.7256359733385
    
  • //接口类型也可以用作字段

    package main
    
    import (
       "fmt"
    )
    
    // Interface types can also be used as fields
    type MyDrawing struct {
       shapes  []Shape
       bgColor string
       fgColor string
    }
    
    func (drawing MyDrawing) Area() float64 {
       totalArea := 0.0
       for _, s := range drawing.shapes {
           totalArea += s.Area()
       }
       return totalArea        
    }
    
    func main() {
       drawing := MyDrawing{
           shapes: []Shape{
               Circle{2},
               Rectangle{3, 5},
               Rectangle{4, 7},
           },
           bgColor: "red",
           fgColor: "white",
       }
    
       fmt.Println("Drawing", drawing)
       fmt.Println("Drawing Area = ", drawing.Area())
    }
    
    # 输出
    Drawing {[{2} {3 5} {4 7}] red white}
    Drawing Area = 55.56637061435917
    

接口的值:接口类型如何处理具体的值

在底层,接口的值可以认为是由值和具体类型组成的元组:

// 接口
(value, type)

接下来让我们看一个例子:

package main

import (
    "fmt"
)

func main() {
    var s Shape

    s = Circle{5}
    fmt.Printf("(%v, %T)\n", s, s)
    fmt.Printf("Shape area = %v\n", s.Area())

    s = Rectangle{4, 7}
    fmt.Printf("(%v, %T)\n", s, s)
    fmt.Printf("Shape area = %v\n", s.Area())
}
# 输出
({5}, main.Circle)
Shape area = 78.53981633974483
({4 7}, main.Rectangle)
Shape area = 28

检出上述程序的输出,并注意变量s如何获得有关该值的信息以及为其分配的Shape的类型。

当我们在接口值上调用方法时,将在其基础类型上执行相同名称的方法。

例如, 在上述程序中,当我们在变量s上调用方法Area()时,它将执行其基础类型的Area()方法。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://www.callicoder.com/golang-interf...

译文地址:https://learnku.com/go/t/46649

本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!