接口是一個(gè)或多個(gè)方法簽名的集合,任何類型的方法集中只要擁有與之對(duì)應(yīng)的全部方法, 就表 它 "實(shí)現(xiàn)" 了該接 , 必須在該類型上顯式添加接口聲明。
引用類型。
接口的使用
一、
package main
import "fmt"
type Mystring string
type Finder interface {
FindVowels() []rune
test()
}
//方法的實(shí)現(xiàn)
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())
}
二、兩個(gè)結(jié)構(gòu)體實(shí)現(xiàn)接口同一個(gè)方法,不同結(jié)構(gòu)體組成的數(shù)組可以直接調(diào)用實(shí)現(xiàn)了相同接口的接口類型參數(shù)的函數(shù)
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
}
//接口類型的函數(shù)參數(shù)
func CalculateTotal(all []SalaryCalculator) int {
sum := 0
for _, v := range all {
sum = sum + v.CalculateSalary()
}
return sum
}
func main() {
//兩個(gè)結(jié)構(gòu)體實(shí)現(xiàn)接口同一個(gè)方法,不同結(jié)構(gòu)體組成的數(shù)組可以直接調(diào)用實(shí)現(xiàn)了相同接口的接口類型參數(shù)的函數(shù)
p1 := Permanent{1, 2333, 23}
p2 := Permanent{2, 3333, 21}
p3 := Contract{3, 2999}
employees := []SalaryCalculator{p1, p2, p3}
fmt.Println(CalculateTotal(employees))
}
三、接口的內(nèi)部表示
可以把接口想象成這樣一個(gè)元組 (type, value)。type 是接口包含
的具體類型,value 是接口包含的具體的值。 讓我們寫一個(gè)程序來理解這一點(diǎn)。
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 接口提供了一個(gè)方法 Tester(),MyFloat 類型實(shí)現(xiàn)了這個(gè)接 口。在第 24 行,我們將 MyFloat 類型的變量 f 賦值給 Test 類型的變 量 t ?,F(xiàn)在 t 的具體類型是 MyFloat 而它的值是 89.7。在第17行, describe 函數(shù)打印接口的值和具體類型。
四、空接口
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.在上面的程序中,我們將實(shí)際類型為 string 的變量 s 傳遞給 assert 函數(shù),assert 函數(shù)嘗試從其中提取出一個(gè) int 值。該程序會(huì)觸 發(fā) panic:panic: interface conversion: interface {} is string, not int。下面就可以解決這個(gè)問題。
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----------------------