一. 接口
1. 概述
- 接口类型具体描述了一系列方法的集合
- 接口类型是一个抽象的类型,不会暴露出他代表的对象内部值的结构和对这个对象的支持的基础操作集合,他只会展示出他们自己的方法。接口类型不能将其实例化
2. 接口的使用
2.1 接口的定义
type Humaner interfance{
SayHi()
}
- 接口里面的方法只有声明没有实现,由其他的自定义类型实现
- 接口的命名习惯以er结尾
- 接口可以匿名嵌入其他接口或者嵌入到结构中
2.2 接口的实现
package main
import "fmt"
type Humaner interface {
SayHi()
}
type Student struct {
name string
id int
}
func (s *Student)SayHi() {
fmt.Printf("Student %s SayHi ", s.name)
}
type Teacher struct {
name string
age int
}
func (t *Teacher)SayHi() {
fmt.Printf("Teacher %s SayHi ", t.name)
}
func main() {
var i Humaner
//只要实现了此接口方法类型,那么该类型的变量(或者接收者类型)就可以给i赋值
s := &Student{"mike" , 20}
i = s
i.SayHi()
t := &Teacher{"ricky" , 30}
i = t
t.SayHi()
}
/*
Student mike SayHi
Teacher ricky SayHi
*/
3. 接口的组合
3.1 接口嵌入
package main
import "fmt"
type Humaner interface {
SayHi()
}
type Personer interface {
Humaner //匿名字段 继承了Humaner接口
Sing(lrc string)
}
type Student struct {
name string
id int
}
//Student 实现了该方法
func (s *Student)SayHi() {
fmt.Printf("Student %s SayHi \n", s.name)
}
func (s *Student)Sing(lrc string) {
fmt.Printf("Student %s Sing %s \n", s.name,lrc)
}
func main() {
var i Personer
s := &Student{"mike" , 66}
i = s
i.SayHi()
i.Sing("miao miao miao")
}
3.2 接口转化
- 超集(Personer)可以转化为子集(Humaner),但是子集(Humaner)不能转化为超集(Personer)
func main() {
var iPro Personer //超集
iPro = &Student{"mike" , 66}
var i Humaner //子集
i = iPro //可以的 超集可以为子集
i.SayHi()
}
4. 空接口
- 不包含任何方法的接口是空接口
- ==所以的类型都实现了空接口==
var v1 interface{} = 1 //把int类型赋值给interface{}
var v2 interface{} = "abc" //把string类型赋值给interface{}
var v3 interface{} = &v2 //把*interface{}类型赋值给interface{}
var v4 interface{} = struct {
X int
}{1} //把int类型赋值给interface{}
- 空接口可以存储任意类型的数值
- 当函数需要接受任意对象实例的时候,我们可以申明为空接口interface{}
5. 类型查询
5.1 comma-ok断言
package main
import (
"fmt"
)
type Student struct {
name string
}
func main() {
i := make([]interface{} , 3)
i[0] = 1
i[1] = "hello"
i[2] = Student{"mike" }
//类型查询
for index , data := range i {
//判断Value是不是int类型, 第一个返回的是值 第二个返回的结果
if value , ok := data.(int) ; ok == true {
fmt.Printf("x [%d] 类型为int , 内容为%d \n" , index , value)
}else if value , ok := data.(string) ; ok == true {
fmt.Printf("x [%d] 类型为string , 内容为 %s \n" , index , value)
}else if value , ok := data.(Student) ; ok == true {
fmt.Printf("x [%d] 类型为string , 内容为%s \n" , index , value.name)
}
}
}
5.2 switch测试
for index , data := range i {
switch t := data.(type) {
case int:
fmt.Printf("x [%d] 类型为int , 内容为%d \n" , index , t)
case string:
fmt.Printf("x [%d] 类型为int , 内容为%s \n" , index , t)
case Student:
fmt.Printf("x [%d] 类型为int , 内容为%s \n" , index , t.name)
}
}