接口是一个或多个方法签名的集合,任何类型的方法集中只要拥有与之对应的全部方法, 就表 它 "实现" 了该接 , 必须在该类型上显式添加接口声明。
引用类型。
接口的使用
一、
package main
import "fmt"
type Mystring string
type Finder interface {
FindVowels() []rune
test()
}
//方法的实现
func (ms Mystring) test() {}
func (ms Mystring) FindVowels() []rune {
var Ru []rune
for _, run := range ms {
if run == 'a' || run == 'e' || run == 'o' || run == 'i' || run == 'u' {
Ru = append(Ru, run)
}
}
return Ru
}
func main() {
var ms Mystring = "hello world"
var V Finder
V = ms
fmt.Println(ms.FindVowels())
fmt.Println(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
}
func (p Permanent) CalculateSalary() int {
return p.basicpay + p.pf
}
func (p Contract) CalculateSalary() int {
return p.basicpay
}
//接口类型的函数参数
func CalculateTotal(all []SalaryCalculator) int {
sum := 0
for _, v := range all {
sum = sum + v.CalculateSalary()
}
return sum
}
func main() {
//两个结构体实现接口同一个方法,不同结构体组成的数组可以直接调用实现了相同接口的接口类型参数的函数
p1 := Permanent{1, 2333, 23}
p2 := Permanent{2, 3333, 21}
p3 := Contract{3, 2999}
employees := []SalaryCalculator{p1, p2, p3}
fmt.Println(CalculateTotal(employees))
}
三、接口的内部表示
可以把接口想象成这样一个元组 (type, value)。type 是接口包含
的具体类型,value 是接口包含的具体的值。 让我们写一个程序来理解这一点。
package main
import "fmt"
type Test interface {
Tester()
}
type MyFloat float64
func (m MyFloat) Tester() {
fmt.Println("lalala", m)
}
func describe(t Test) {
fmt.Printf("Interface type %T value %v\n", t, t)
}
func main() {
var t Test
f := MyFloat(89.7)
t = f
describe(t)
t.Tester()
}
Test 接口提供了一个方法 Tester(),MyFloat 类型实现了这个接 口。在第 24 行,我们将 MyFloat 类型的变量 f 赋值给 Test 类型的变 量 t 。现在 t 的具体类型是 MyFloat 而它的值是 89.7。在第17行, describe 函数打印接口的值和具体类型。
四、空接口
1.可以接收任何类型
package main
import "fmt"
//空接口
func describe1(i interface{}) {
fmt.Printf("Type %T,value %v\n", i, i)
}
func main() {
s := "Hello World"
describe1(s)
//
// i := 55
// describe1(i)
//
// strt := struct {
// name string
// age int
// }{
// name: "Nancy",
// age: 21,
// }
// describe1(strt)
}
2.用空接口来提取类型的值
package main
import (
"fmt"
)
func assert(i interface{}) {
s := i.(int)
fmt.Println(s)
}
func main() {
var s interface{} = "Steven Paul"
assert(s)
}
3.在上面的程序中,我们将实际类型为 string 的变量 s 传递给 assert 函数,assert 函数尝试从其中提取出一个 int 值。该程序会触 发 panic:panic: interface conversion: interface {} is string, not int。下面就可以解决这个问题。
package main
import ( "fmt"
)
func assert(i interface{}) { v, ok := i.(int) fmt.Println(v, ok)
}
func main() {
var s interface{} = 56
assert(s)
var i interface{} = "Steven Paul" assert(i)
}
五、接口嵌套
package main
import (
"fmt"
)
//接口嵌套
type SalaryCalculator interface {
DisplaySalary()
}
type LeaveCalculator interface {
CalculateLeavesLeft()
}
type EmployeeOperations interface {
SalaryCalculator
LeaveCalculator
}
func (e Employee) DisplaySalary() {
fmt.Sprintf("employee's name:%d\n", 234)
}
func (e Employee) CalculateLeavesLeft() {
fmt.Println("employee's ID:", e.id)
}
func main() {
//接口嵌套
var Eop EmployeeOperations = Employee{6, "coco"}
// Eop = emp
Eop.DisplaySalary()
Eop.CalculateLeavesLeft()
}
-------------------end----------------------