教程 > Go 教程 > Go 基础 阅读:259

Go 语言接口 Interface 详解

在 Go 中,可以认为接口是一组方法的集合。当一个类型实现了接口中的所有方法时,就说它实现了接口。它与 OOP 世界非常相似。接口指定类型应该具有哪些方法,类型决定如何实现这些方法。

接口的声明语法如下

type interface_name interface {
   method_name1 [return_type]
   method_name2 [return_type]
   method_name3 [return_type]
   ...
   method_namen [return_type]
}

接口的声明和实现

让我们直接创建接口并实现它。

package main

import (  
    "fmt"
)

//接口定义
type VowelsFinder interface {  
    FindVowels() []rune
}

type MyString string

//MyString 实现VowelsFinder接口
func (ms MyString) FindVowels() []rune {  
    var vowels []rune
    for _, rune := range ms {
        if rune == 'a' || rune == 'e' || rune == 'i' || rune == 'o' || rune == 'u' {
            vowels = append(vowels, rune)
        }
    }
    return vowels
}

func main() {  
    name := MyString("Sam Anderson")
    var v VowelsFinder
    v = name
    fmt.Printf("元音字符是 %c", v.FindVowels())

}

运行示例

上述代码执行结果如下

元音字符是 [a e o]

上面的例子教我们如何创建和实现接口,但它并没有真正展示接口的实际用途。

如果我们在上面的程序中使用 name.FindVowels()而不是 v.FindVowels(),也能输出相同的结果,但是这样并不会使用接口。

现在让我们看一个接口的实际使用的示例。

我们将编写一个简单的程序,根据员工的个人工资计算公司的总费用。

package main

import (  
    "fmt"
)

// 定义一个接口
type SalaryCalculator interface {  
    CalculateSalary() int
}

type Permanent struct {  
    empId    int
    basicpay int
    pf       int
}

type Contract struct {  
    empId    int
    basicpay int
}

// 永久员工的薪资是 basicpay 与 pf 的和
func (p Permanent) CalculateSalary() int {  
    return p.basicpay + p.pf
}

// 合同工只有basicpay
func (c Contract) CalculateSalary() int {  
    return c.basicpay
}

// 通过迭代SalaryCalculator 切片,计算员工的薪资综合,从而计算出公司的总花费
func totalExpense(s []SalaryCalculator) {  
    expense := 0
    for _, v := range s {
        expense = expense + v.CalculateSalary()
    }
    fmt.Printf("每个月总花费: $%d", expense)
}

func main() {  
    pemp1 := Permanent{
        empId:    1,
        basicpay: 5000,
        pf:       20,
    }
    pemp2 := Permanent{
        empId:    2,
        basicpay: 6000,
        pf:       30,
    }
    cemp1 := Contract{
        empId:    3,
        basicpay: 3000,
    }
    employees := []SalaryCalculator{pemp1, pemp2, cemp1}
    totalExpense(employees)
}

运行示例

上述代码执行结果如下

每个月总花费: $14050

对于上例来说,使用接口的优势在于:totalExpense可以扩展到任何新员工类型而无需任何代码更改。假设公司增加了Freelancer一种工资结构不同的新型员工。可以只是将Freelancer在 slice 参数中传递给 totalExpense()方法, 而无需对函数totalExpense进行任何一行代码更改。

查看笔记

扫码一下
查看教程更方便