接口(interface)
接口是一组方法签名的集合,定义了类型应实现的行为。实现是隐式的:只要类型具有接口所需方法,就实现
该接口。
定义格式
1 2 3 4
| type 接口名 interface { Method1(arg T) R Method2() error }
|
例如
1 2 3 4 5 6 7 8 9 10 11 12 13
| type Stringer interface { String() string }
func Print(s Stringer) { fmt.Println(s.String()) }
type Person struct { Name string }
func (p Person) String() string { return p.Name }
Print(Person{Name: "Tom"})
|
接口与面向对象
Go的面向对象包含三大要素:接口、方法、结构体
定制接口 - 接口要求方法 - 存在方法满足接口要求 - struct存储信息 - 调用接口
方法需要结构体作为接受者,也就是结构体与方法是“封装”一步的关键
如图

多接口
代码实现
1 2 3 4 5 6 7 8 9 10 11 12
| type 接口名 interface { 方法名(参数) 返回值(方法类型) ... }
type 结构体名 struct { ... }
func (结构体变量名 结构体名/*方法接收器,定义方法操作的对象*/) 方法名(参数) 返回值{ ... }
|
多态
通过用不同类型实现同一接口,可以实现接口的多态表现
解耦
通过接口定义依赖关系,降低模块之间的耦合
区别于Java类OOP式面向对象的Is-a关系,Go的Can-do关系不要求强制存在父类、子类和方法之间的访问修饰符定义等强耦合关系
泛化
使用空借口interface{}可表示任意类型
空接口
空接口 interface{} 可以表示任何类型
1 2 3
| var x interface{} x = 123 x = "hello
|
类型断言与类型选择
1 2 3
| var v interface{} = "abc" s := v.(string) s, ok := v.(string)
|
1 2 3 4 5 6 7
| switch t := v.(type) { case int: case string: default: }
|
泛型(any)
与空接口类似,可以表示任何类型
不同的是,空接口在编译时容易发生类型安全错误,需要频繁类型断言
而泛型any会自动保证编译时类型安全,编译器会为每个使用的具体类型生成一份特化代码
拓展知识之后会逐渐接触