乐趣区

关于后端:61-Go语言中接口使用样例

正如前文提到,Go 语言并没有类的定义,接口能够说 Go 语言最靠近于类的实现形式,然而更轻量。对于接口的学习,如果从原理层面了解学习起来比较慢,所以倡议先从代码应用维度进行了解,最终回归到原理层面加深了解。

需要与剖析

假如咱们有一组图形,须要计算每个图形的面积,并计算他们的面积之和。那么最简略的办法就是别离计算他们的面积,并进行相加,咱们来尝试实现一下。

不应用接口的实现

在这个代码实现中,咱们须要将两种不同形态,矩形 (rect) 和圆形 (circle) 的面积求和,因而咱们定义了如下内容:

  • 两个构造体,矩形是长和宽,圆形是半径
  • 别离实现了两个求面积的办法 area(),矩形的面积等于长乘以宽,而圆形面积则是半径的平方乘以 Pi
  • 在求和局部,咱们间接定义了一个 float64 的数组,将面积间接存入该数组中
  • 通过循环进行求和

尽管上述形式可能满足咱们的需要,然而如果咱们须要减少一个计算周长的办法时,咱们的代码会变得十分冗余并且可读性变差,因而咱们用接口尝试来革新咱们的代码。

package main

import (
    "fmt"
    "math"
)

type rect struct {
    width float64
    height float64
}

func (r rect) area() float64 {return r.width * r.height}

type circle struct {radius float64}

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

func main() {
    var areaSum float64
    
    // Intial circle and rect struct type
    c1 := circle{2.5}
    r1 := rect{3, 4}
    
    // Save all area results into an array
    shapeAreas := []float64{c1.area(), r1.area()}
    
    // Sum all area together
    areaSum = 0
    for _, area := range shapeAreas {areaSum += area}
    
    fmt.Printf("Sum area = %v\n", areaSum)
}

应用接口的实现

相较于上述代码,咱们做了如下优化:

  • 定义了一个新的 interface shape,蕴含一个 area()办法,即实现了 area()的 struct,就实现了 shape 接口
  • 在构造体定义,area()计算局部咱们并没有批改
  • 在主函数中,咱们从新定义了一个类型为 shape interface 的数组,该数组中无须再计算 area(),只须要将两个不通类型寄存在该数组中
  • 在循环过程中,咱们间接调用每个 shape interface 中的 area()办法,即可实现面积求和
package main

import (
    "fmt"
    "math"
)

// Define a new interface, contain a method define and type is float64
type shape interface {area() float64
}

type rect struct {
    width float64
    height float64
}

func (r rect) area() float64 {return r.width * r.height}

type circle struct {radius float64}

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

func main() {
    var areaSum float64
    
    // Intial circle and rect struct type
    c1 := circle{2.5}
    r1 := rect{3, 4}
    
    // Previous: Save all area results into an array
    // Previous: shapeAreas := []float64{c1.area(), r1.area()}
    
    // Define an array with new shape interface
    shapes := []shape{c1, r1}
    
    // Previous: Sum all area together
    areaSum = 0
    // Previous: for _, area := range shapeAreas {
    // Previous:     areaSum += area
    // Previous: }
    
    // Implement a new loop
    for _, shape := range shapes {areaSum += shape.area()
    }
    
    fmt.Printf("Sum area = %v\n", areaSum)
}

接口作为函数参数

进一步优化代码,咱们将接口作为参数,在主函数中调用时,只须要传入相应类型就会主动依据类型调用相应的计算面积的办法。

package main

import (
    "fmt"
    "math"
)

// Define a new interface, contain a method define and type is float64
type shape interface {area() float64
}

type rect struct {
    width float64
    height float64
}

// NOTE: 接口类型为 rect
func (r rect) area() float64 {return r.width * r.height}

type circle struct {radius float64}

// NOTE: 接口类型为 circle
func (c circle) area() float64 {return math.Pi * c.radius * c.radius}

func getArea(s shape) float64 {return s.area()
}

func main() {
    var areaSum float64

    // Intial circle and rect struct type
    c1 := circle{2.5}
    r1 := rect{3, 4}

    // Previous: Save all area results into an array
    // Previous: shapeAreas := []float64{c1.area(), r1.area()}

    // Define an array with new shape interface
    shapes := []shape{c1, r1}

    // Previous: Sum all area together
    areaSum = 0
    // Previous: for _, area := range shapeAreas {
    // Previous:     areaSum += area
    // Previous: }

    // Implement a new loop
    for _, shape := range shapes {areaSum += getArea(shape)
    }

    fmt.Printf("Sum area = %v\n", areaSum)
}

本文由博客一文多发平台 OpenWrite 公布!

退出移动版