扫码一下
查看教程更方便
在 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
进行任何一行代码更改。