GO_面向对象---接口
发布时间:2026/7/16 4:01:43
分类:文化教育
浏览:1234

一、接口核心概念鸭子类型1. 什么是鸭子类型Go 采用鸭子类型duck typing实现接口核心思想如果一个事物走路像鸭子、游泳像鸭子、叫声像鸭子那它就是鸭子。翻译到 Go 语言我们不关心变量底层是什么结构体 / 类型只关心它具备哪些行为方法。只要某个类型实现了接口规定的全部方法就自动实现该接口无需显式声明实现关系。2. 接口本质接口是一组方法签名的集合只定义方法声明不提供方法实现由自定义结构体、基础类型等去完成方法实现。核心特点关注行为不关注类型。二、基础接口定义与使用1. 定义接口语法go// 定义Humaner接口仅规定sayhi()方法 type Humaner interface { sayhi() // 只有方法声明无方法体 }2. 结构体实现接口只要结构体绑定了接口全部方法就自动实现该接口。注意示例中使用指针接收者赋值时必须传结构体指针。gopackage main import fmt // 1. 定义接口 type Humaner interface { sayhi() } // 2. 定义两个结构体 type Student struct { name string id int } type Teacher struct { addr string group string } // Student指针接收者实现sayhi()满足Humaner接口 func (tmp *Student) sayhi() { fmt.Printf(Student[%s, %d] sayhi\n, tmp.name, tmp.id) } // Teacher指针接收者实现sayhi()满足Humaner接口 func (tmp *Teacher) sayhi() { fmt.Printf(Teacher[%s, %s] sayhi\n, tmp.addr, tmp.group) } func main() { // 3. 定义接口变量 var i Humaner // 结构体指针赋值给接口变量 s : Student{mike, 666} i s i.sayhi() t : Teacher{bj, go} i t i.sayhi() }运行结果plaintextStudent[mike, 666] sayhi Teacher[bj, go] sayhi三、接口实现多态多态核心同一个接口 / 同一个函数传入不同实现类型执行不同逻辑。1. 函数参数为接口标准多态写法go// 接收Humaner接口参数统一调用sayhi() func WhoSayHi(i Humaner) { i.sayhi() } func main() { s : Student{mike, 666} t : Teacher{bj, go} // 同一函数不同入参不同输出 多态 WhoSayHi(s) WhoSayHi(t) }2. 接口切片批量存储多类型接口切片可以存放任意实现该接口的类型变量循环统一调用方法gofunc main() { s : Student{mike, 666} t : Teacher{bj, go} // 创建Humaner接口切片 x : make([]Humaner, 2) x[0] s x[1] t // range遍历统一执行方法 for _, item : range x { item.sayhi() } }四、接口嵌套接口继承Go 没有类继承通过匿名字段接口实现接口嵌套接口继承子接口会自动拥有父接口的所有方法结构体想要实现子接口必须同时实现父接口 子接口全部方法超集接口方法更多不能赋值给子集接口子集可以赋值给超集。gopackage main import fmt // 父接口子集 type Humaner interface { sayhi() } // 子接口超集嵌套Humaner继承sayhi() type Personer interface { Humaner // 匿名字段嵌套接口 sing(lrc string) // 自身新增方法 } type Student struct { name string id int } // 实现父接口方法 func (tmp *Student) sayhi() { fmt.Printf(Student[%s, %d] sayhi\n, tmp.name, tmp.id) } // 实现子接口新增方法 func (tmp *Student) sing(lrc string) { fmt.Println(Student在唱着, lrc) } func main() { // 定义超集接口变量 var i Personer s : Student{mike, 666} i s i.sayhi() // 继承自Humaner的方法 i.sing(七里香) }接口转换规则子集接口方法少→ 超集接口方法多允许超集接口方法多→ 子集接口方法少编译报错不允许govar iPro Personer // 超集接口 var i Humaner // 子集接口 iPro i // 错误超集无法接收子集 i iPro // 正确子集可以接收超集五、空接口 interface {}1. 定义与特性interface{}是空接口不含任何方法因此 Go 中所有类型自动实现空接口。作用万能容器等价于 C 语言void*可以存储任意类型数据。gopackage main import fmt func main() { var i interface{} i 123 fmt.Println(i , i) i golang fmt.Println(i , i) i Student{lily, 888} fmt.Println(i , i) }2. 可变参数空接口函数参数声明arg ...interface{}可接收任意数量、任意类型参数gofunc showAll(arg ...interface{}) { for _, v : range arg { fmt.Println(v) } } func main() { showAll(10, test, Student{tom, 111}) }六、类型断言类型查询空接口存储数据后会丢失原有类型信息通过类型断言还原底层真实类型两种写法if判断、switch type。方式 1if 类型断言语法val, ok : 空接口变量.(目标类型)val转换后的值ok布尔值true 代表类型匹配成功gofunc main() { // 空接口切片存储多类型数据 slice : make([]interface{}, 3) slice[0] 666 slice[1] hello go slice[2] Student{mike, 666} for _, data : range slice { // 判断是否int if val, ok : data.(int); ok { fmt.Printf(int类型%d\n, val) } else if val, ok : data.(string); ok { fmt.Printf(string类型%s\n, val) } else if val, ok : data.(Student); ok { fmt.Printf(Student结构体%v\n, val) } } }方式 2type-switch专门用于批量判断空接口底层类型代码更简洁gofunc main() { slice : make([]interface{}, 3) slice[0] 666 slice[1] hello go slice[2] Student{mike, 666} for _, data : range slice { switch val : data.(type) { case int: fmt.Printf(整数%d\n, val) case string: fmt.Printf(字符串%s\n, val) case Student: fmt.Printf(学生结构体%v\n, val) default: fmt.Printf(未知类型%T值%v\n, val, val) } } }七、总结Go 接口基于鸭子类型无需显式 implement实现全部方法即自动实现接口接口是方法集合只定义行为不关心实体类型接口作为函数参数 / 切片实现多态特性接口嵌套实现 “继承”转换规则子集可接收超集反之不行interface{}空接口是万能类型存储任意数据类型断言 /type-switch 用于还原空接口底层真实类型。