13-接口
什么是接口
接口就是一系列方法的集合
当一个结构体定义了接口中的所有方法,我们称它实现了该接口。这与面向对象编程(OOP)的说法很类似。接口指定了一个类型应该具有的方法,并由该类型决定如何实现这些方法
语法
type 接口名 interface{
方法一
方法二
}
接口的声明与实现
package main import "fmt" //定义一个鸭子接口(一系列方法的集合) type Duck interface { run() speak() } //定义普通鸭子结构体(一系列属性的集合) type PDuck struct { name string age int } //定义唐老鸭的结构体 type TDuck struct { name string age int wife bool } //实现run方法 func (p PDuck)run() { fmt.Println(p.name,"我在走路") } //实现speak方法 func (p PDuck)speak() { fmt.Println(p.name,"我在讲话") } //唐老鸭实现接口(实现两个方法) func (T TDuck)run() { fmt.Println(T.name,"我在走路") } func (T TDuck)speak() { fmt.Println(T.name,"我在说话") }
func main() { pD:=PDuck{name:"水鸭子"} //结构体赋值 tD:=TDuck{name:"唐老鸭"} pD.speak() //实现接口方法 tD.speak() var p Duck //通过接口直接访问方法 p=pD p.speak() } #结果 水鸭子 我在讲话 唐老鸭 我在说话 水鸭子 我在讲话
类型断言
func speak(p Duck) { switch a:=p.(type) { case PDuck: //判断好了,你是普通鸭子,把鸭子名字拿出来 fmt.Println("你是普通鸭子") fmt.Println(a.name) case TDuck: //判断好了,你是唐老鸭,把唐老鸭的wife拿出来 fmt.Println("你是唐老鸭") fmt.Println(a.wife) } }
空接口
没有包含方法的接口称为空接口。空接口表示为 interface{}
。由于空接口没有方法,因此所有类型都实现了空接口。
package main import "fmt" type Empty interface { //空接口 } type TDuck2 struct { name string age string wife bool } func main() { test(1) test("ssss") test(TDuck2{}) test(10.45) } func test(a interface{}) { //因为test函数接收空接口作为参数,因此可以给这个函数传递任何类型。用interface{}接收空接口 switch a.(type) { //做断言判断 case int: fmt.Println("你是int类型") case string: fmt.Println("你是string ") case TDuck2: fmt.Println("你是唐老鸭") default: fmt.Println("我不知道你是什么类型") } }
实现多个接口
就是一个结构体实现多个接口的方法
package main import ( "fmt" ) type SalaryCalculator interface { DisplaySalary() } type LeaveCalculator interface { CalculateLeavesLeft() int } type Employee struct { firstName string lastName string basicPay int pf int totalLeaves int leavesTaken int } func (e Employee) DisplaySalary() { fmt.Printf("%s %s has salary $%d", e.firstName, e.lastName, (e.basicPay + e.pf)) } func (e Employee) CalculateLeavesLeft() int { return e.totalLeaves - e.leavesTaken } func main() { e := Employee { firstName: "Naveen", lastName: "Ramanathan", basicPay: 5000, pf: 200, totalLeaves: 30, leavesTaken: 5, } e.DisplaySalary() e.CalculateLeavesLeft() fmt.Println("\nLeaves left =", e.CalculateLeavesLeft()) //除了上面可以直接用e.方法名获得,还可以按照下面这种写法 //var s SalaryCalculator = e //把e赋值给了SalaryCalculator类型的接口变量 //s.DisplaySalary() //然后调用DisplaySalary方法 //var l LeaveCalculator = e //把e赋值给了LeaveCalculator类型的接口变量 } #结果 Naveen Ramanathan has salary $5200 Leaves left = 25
接口的嵌套
尽管 Go 语言没有提供继承机制,但可以通过嵌套其他的接口,创建一个新接口。
package main import ( "fmt" ) type SalaryCalculator interface { DisplaySalary() } type LeaveCalculator interface { CalculateLeavesLeft() int } type EmployeeOperations interface { //嵌套了接口,就可以使用接口的方法 SalaryCalculator LeaveCalculator } type Employee struct { firstName string lastName string basicPay int pf int totalLeaves int leavesTaken int } func (e Employee) DisplaySalary() { fmt.Printf("%s %s has salary $%d", e.firstName, e.lastName, (e.basicPay + e.pf)) } func (e Employee) CalculateLeavesLeft() int { return e.totalLeaves - e.leavesTaken } func main() { e := Employee { firstName: "Naveen", lastName: "Ramanathan", basicPay: 5000, pf: 200, totalLeaves: 30, leavesTaken: 5, } var empOp EmployeeOperations = e empOp.DisplaySalary() fmt.Println("\nLeaves left =", empOp.CalculateLeavesLeft()) } #结果 Naveen Ramanathan has salary $5200 Leaves left = 25
接口的零值
接口的零值nil,所以接口是引用类型
package main import "fmt" type Describer interface { Describe() } func main() { var d1 Describer if d1 == nil { fmt.Printf("d1 is nil and has type %T value %v\n", d1, d1) } }